"""Obtain a Google Drive refresh token for the application. Run this once from a development machine that has a browser. It opens a local OAuth redirect server, asks you to log in, and prints the refresh token. Usage: python app/supporting_scripts/get_refresh_token.py Requires: pip install google-auth-oauthlib Before running: 1. Create a Google Cloud project and enable the Drive API. 2. Create a **Desktop** OAuth 2.0 client ID. 3. Add your email as a test user in the OAuth consent screen. 4. Run this script and paste the values when prompted. """ import os import sys def _prompt(label, env_name, default=""): """Ask the user for a value, accepting an env-var fallback or a default.""" candidate = os.getenv(env_name) or default hint = f" [{candidate}]" if candidate else "" raw = input(f"{label}{hint}: ").strip() if raw: return raw if candidate: return candidate return default def _validate_client_id(client_id): """Warn if the client ID doesn't look like a real OAuth client ID.""" if client_id == "YOUR_CLIENT_ID.apps.googleusercontent.com": print("[ERROR] You must provide a real client ID from the Google Cloud console.") return False if not client_id.endswith(".apps.googleusercontent.com"): print( f"[WARNING] Client ID should end with '.apps.googleusercontent.com'.\n" f" Got: {client_id!r}\n" f" If this is a placeholder, the OAuth request will fail.\n" ) return True def _validate_client_secret(secret): if secret == "YOUR_CLIENT_SECRET": print("[ERROR] You must provide a real client secret from the Google Cloud console.") return False # The GOCSPX- prefix is now used by every client type, so it no longer # tells us anything about whether the client was created as a Desktop app. return True def main(): print("=" * 60) print("Google Drive Refresh Token — Setup") print("=" * 60) print() # When both env vars are set, skip prompts entirely for headless runs. env_id = os.getenv("GOOGLE_DRIVE_CLIENT_ID") env_secret = os.getenv("GOOGLE_DRIVE_CLIENT_SECRET") if env_id and env_secret: client_id = env_id client_secret = env_secret print(f"Using Client ID from environment: {client_id[:30]}...") else: print("Enter your Google Cloud OAuth credentials.") print("You can also set GOOGLE_DRIVE_CLIENT_ID and GOOGLE_DRIVE_CLIENT_SECRET") print("environment variables and re-run to skip the prompts.") print() client_id = _prompt("Client ID", "GOOGLE_DRIVE_CLIENT_ID") client_secret = _prompt("Client Secret", "GOOGLE_DRIVE_CLIENT_SECRET") if not _validate_client_id(client_id) or not _validate_client_secret(client_secret): sys.exit(1) print() print("Opening browser to authenticate with Google...") print("(If it doesn't open, copy the URL below into your browser.)") print() from google_auth_oauthlib.flow import InstalledAppFlow SCOPE = "https://www.googleapis.com/auth/drive.file" client_config = { "installed": { "client_id": client_id, "client_secret": client_secret, "redirect_uris": ["http://localhost"], "auth_uri": "https://accounts.google.com/o/oauth2/auth", "token_uri": "https://oauth2.googleapis.com/token", } } flow = InstalledAppFlow.from_client_config(client_config, scopes=[SCOPE]) credentials = flow.run_local_server(host="localhost", port=8080, open_browser=True) print() print("=" * 60) print("SUCCESS — copy these values into your .env file:") print("=" * 60) print() print("DOCUMENT_STORAGE_BACKEND=google_drive") print(f"GOOGLE_DRIVE_CLIENT_ID={credentials.client_id}") print(f"GOOGLE_DRIVE_CLIENT_SECRET={client_secret}") print(f"GOOGLE_DRIVE_REFRESH_TOKEN={credentials.refresh_token}") print("GOOGLE_DRIVE_FOLDER_ID=") print() return 0 if __name__ == "__main__": sys.exit(main())