Spaces:
Sleeping
Sleeping
Antigravity
feat: Cloud-ready release of AI Gmail Agent with premium glassmorphism telemetry dashboard and Dockerfile
e895030 | from google.auth.transport.requests import Request | |
| from google.oauth2.credentials import Credentials | |
| from google_auth_oauthlib.flow import InstalledAppFlow | |
| import os | |
| import json | |
| from loguru import logger | |
| from config import GMAIL_TOKEN_JSON, GMAIL_CREDENTIALS_JSON, GMAIL_TOKEN_FILE, GMAIL_CREDENTIALS_FILE | |
| SCOPES = ["https://www.googleapis.com/auth/gmail.modify"] | |
| def authenticate(): | |
| creds = None | |
| # 1. Try loading authorized user token from environment variable | |
| if GMAIL_TOKEN_JSON: | |
| try: | |
| logger.info("π Loading Gmail token from GMAIL_TOKEN_JSON environment variable...") | |
| info = json.loads(GMAIL_TOKEN_JSON) | |
| creds = Credentials.from_authorized_user_info(info, SCOPES) | |
| logger.info("β Gmail token successfully loaded from environment variable") | |
| except Exception as e: | |
| logger.error(f"β Failed to load token from GMAIL_TOKEN_JSON environment variable: {e}") | |
| creds = None | |
| # 2. Try loading from local token file | |
| if not creds and os.path.exists(GMAIL_TOKEN_FILE): | |
| try: | |
| logger.info(f"π Loading Gmail token from file: {GMAIL_TOKEN_FILE}...") | |
| creds = Credentials.from_authorized_user_file(GMAIL_TOKEN_FILE, SCOPES) | |
| logger.info("β Gmail token successfully loaded from file") | |
| except Exception as e: | |
| logger.error(f"β Failed to load token from file {GMAIL_TOKEN_FILE}: {e}") | |
| creds = None | |
| # 3. If credentials don't exist or are invalid, handle renewal/flow | |
| if not creds or not creds.valid: | |
| if creds and creds.expired and creds.refresh_token: | |
| try: | |
| logger.info("π Gmail access token expired. Refreshing token...") | |
| creds.refresh(Request()) | |
| logger.info("β Gmail token successfully refreshed") | |
| # If we're local and loaded from file, update the file | |
| if os.path.exists(GMAIL_TOKEN_FILE): | |
| try: | |
| with open(GMAIL_TOKEN_FILE, "w") as f: | |
| f.write(creds.to_json()) | |
| except Exception as e: | |
| logger.warning(f"Could not save refreshed token to file: {e}") | |
| except Exception as e: | |
| logger.error(f"β Failed to refresh Gmail token: {e}") | |
| creds = None | |
| if not creds: | |
| # Check if we are running in a headless environment (like HF Spaces) | |
| is_headless = os.getenv("SPACE_ID") is not None or os.getenv("PORT") is not None | |
| if is_headless: | |
| logger.error("β Gmail authorization is missing. In headless/cloud environments, please set GMAIL_TOKEN_JSON environment variable with your token.json contents!") | |
| raise RuntimeError("Gmail credentials are not configured. Please set GMAIL_TOKEN_JSON environment variable in Hugging Face Secrets.") | |
| logger.info("π Authenticating via local browser flow...") | |
| # Determine how to load client secrets | |
| if GMAIL_CREDENTIALS_JSON: | |
| try: | |
| secrets_info = json.loads(GMAIL_CREDENTIALS_JSON) | |
| flow = InstalledAppFlow.from_client_config(secrets_info, SCOPES) | |
| except Exception as e: | |
| logger.error(f"β Failed to parse client secrets from GMAIL_CREDENTIALS_JSON: {e}") | |
| raise | |
| elif os.path.exists(GMAIL_CREDENTIALS_FILE): | |
| flow = InstalledAppFlow.from_client_secrets_file(GMAIL_CREDENTIALS_FILE, SCOPES) | |
| else: | |
| logger.error(f"β Missing client credentials. GMAIL_CREDENTIALS_FILE ({GMAIL_CREDENTIALS_FILE}) not found!") | |
| raise FileNotFoundError(f"Missing {GMAIL_CREDENTIALS_FILE} or GMAIL_CREDENTIALS_JSON environment variable.") | |
| try: | |
| creds = flow.run_local_server( | |
| port=8080, | |
| prompt="consent", | |
| access_type="offline", | |
| open_browser=True | |
| ) | |
| with open(GMAIL_TOKEN_FILE, "w") as f: | |
| f.write(creds.to_json()) | |
| logger.info(f"β Authorization successful! token saved to {GMAIL_TOKEN_FILE}") | |
| except Exception as e: | |
| logger.error(f"β Authorization flow failed: {e}") | |
| raise | |
| return creds |