Files
ryan 82f16bfd6a Add Google Calendar and Gmail integration via Python SDK
Replaces the gws CLI subprocess approach with google-api-python-client.
Adds get_calendar_events, create_calendar_event, gmail_search_emails, and
gmail_get_email as LangChain tools; all admin-gated and auto-enabled when
token.json is present. Includes uv-runnable scripts/google_auth.py for
one-time OAuth2 setup.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-09-16 08:43:18 -04:00

63 lines
1.7 KiB
Python

# /// script
# requires-python = ">=3.13"
# dependencies = [
# "google-auth-oauthlib>=1.0.0",
# ]
# ///
"""One-time OAuth2 setup to generate token.json for Google Calendar and Gmail.
Usage:
uv run scripts/google_auth.py [--credentials credentials.json] [--token token.json]
Requires credentials.json downloaded from Google Cloud Console
(APIs & Services → Credentials → OAuth 2.0 Client ID → Desktop app).
"""
import argparse
import sys
from pathlib import Path
from google_auth_oauthlib.flow import InstalledAppFlow
SCOPES = [
"https://www.googleapis.com/auth/calendar.events",
"https://www.googleapis.com/auth/gmail.readonly",
]
def main():
parser = argparse.ArgumentParser(description="Authorize Google APIs for raggr")
parser.add_argument(
"--credentials",
default="credentials.json",
help="Path to OAuth2 credentials JSON from Google Cloud Console",
)
parser.add_argument(
"--token",
default="token.json",
help="Output path for the generated token file",
)
args = parser.parse_args()
creds_path = Path(args.credentials)
if not creds_path.exists():
print(f"Error: credentials file not found: {creds_path}")
print(
"Download it from Google Cloud Console → APIs & Services → Credentials → OAuth 2.0 Client ID"
)
sys.exit(1)
flow = InstalledAppFlow.from_client_secrets_file(str(creds_path), SCOPES)
creds = flow.run_local_server(port=0)
token_path = Path(args.token)
token_path.write_text(creds.to_json())
print(f"Token saved to {token_path}")
print(
f"Mount this file into Docker: - ./{token_path}:/app/config/google-token.json:ro"
)
if __name__ == "__main__":
main()