Spaces:
No application file
No application file
File size: 8,478 Bytes
93dae80 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 |
# import json
# import os
# from typing import Type
# from dotenv import load_dotenv
# from langchain.pydantic_v1 import BaseModel, Field
# from langchain_core.tools import BaseTool
# from slack_sdk.errors import SlackApiError
# from datetime import datetime
# from google_auth_oauthlib.flow import InstalledAppFlow
# from googleapiclient.discovery import build
# from google.oauth2.credentials import Credentials
# from google.auth.transport.requests import Request
# from config import client
# SCOPES = ['https://www.googleapis.com/auth/calendar']
# TOKEN_DIR = "token_files"
# TOKEN_FILE = f"{TOKEN_DIR}/token.json"
# def create_service(client_secret_file, api_name, api_version, user_id, *scopes):
# """
# Create a Google API service instance using stored credentials for a given user.
# Parameters:
# - client_secret_file (str): Path to your client secrets JSON file.
# - api_name (str): The Google API service name (e.g., 'calendar').
# - api_version (str): The API version (e.g., 'v3').
# - user_id (str): The unique identifier for the user (e.g., Slack user ID).
# - scopes (tuple): A tuple/list of scopes. (Pass as: [SCOPES])
# Returns:
# - service: The built Google API service instance, or None if authentication is required.
# """
# scopes = list(scopes[0]) # Unpack scopes
# creds = None
# user_token_file = os.path.join(TOKEN_DIR, f"token.json")
# if os.path.exists(user_token_file):
# try:
# creds = Credentials.from_authorized_user_file(user_token_file, scopes)
# except ValueError as e:
# print(f"Error loading credentials: {e}")
# # os.remove(user_token_file)
# creds = None
# print(creds)
# # If credentials are absent or invalid, we cannot proceed.
# if not creds or not creds.valid:
# if creds and creds.expired and creds.refresh_token:
# try:
# creds.refresh(Request())
# except Exception as e:
# print(f"Error refreshing token: {e}")
# return None
# else:
# print("No valid credentials available. Please re-authenticate.")
# return None
# # Save the refreshed token.
# with open(user_token_file, 'w') as token_file:
# token_file.write(creds.to_json())
# try:
# service = build(api_name, api_version, credentials=creds, static_discovery=False)
# return service
# except Exception as e:
# print(f"Failed to create service instance for {api_name}: {e}")
# os.remove(user_token_file) # Remove the token file if it's causing issues.
# return None
# def construct_google_calendar_client(user_id):
# """
# Constructs a Google Calendar API client for the specified user.
# Parameters:
# - user_id (str): The unique user identifier (e.g., Slack user ID).
# Returns:
# - service: The Google Calendar API service instance or None if not authenticated.
# """
# API_NAME = 'calendar'
# API_VERSION = 'v3'
# return create_service('credentials.json', API_NAME, API_VERSION, user_id, SCOPES)
import json
import os
from datetime import datetime
import psycopg2
from dotenv import load_dotenv
from google.oauth2.credentials import Credentials
from google.auth.transport.requests import Request
from googleapiclient.discovery import build
# Load environment variables from a .env file
load_dotenv()
# Database helper functions
def load_token(team_id, user_id, service):
conn = psycopg2.connect(os.getenv('DATABASE_URL'))
cur = conn.cursor()
cur.execute('SELECT token_data FROM Tokens WHERE team_id = %s AND user_id = %s AND service = %s', (team_id, user_id, service))
row = cur.fetchone()
cur.close()
conn.close()
print(f"DB ROW: {row[0]}")
return json.loads(row[0]) if row else None
def save_token(team_id, user_id, service, token_data):
"""
Save token data to the database for a specific team, user, and service.
Parameters:
team_id (str): The Slack team ID.
user_id (str): The Slack user ID.
service (str): The service name (e.g., 'google').
token_data (dict): The token data to save (e.g., {'access_token', 'refresh_token', 'expires_at'}).
"""
conn = psycopg2.connect(os.getenv('DATABASE_URL'))
cur = conn.cursor()
cur.execute(
'''
INSERT INTO Tokens (team_id, user_id, service, token_data, updated_at)
VALUES (%s, %s, %s, %s, %s)
ON CONFLICT (team_id, user_id, service)
DO UPDATE SET token_data = %s, updated_at = %s
''',
(
team_id, user_id, service, json.dumps(token_data), datetime.now(),
json.dumps(token_data), datetime.now()
)
)
conn.commit()
cur.close()
conn.close()
def create_service(team_id, user_id, api_name, api_version, scopes):
"""
Create a Google API service instance using stored credentials for a given user.
Parameters:
team_id (str): The Slack team ID.
user_id (str): The Slack user ID.
api_name (str): The Google API service name (e.g., 'calendar').
api_version (str): The API version (e.g., 'v3').
scopes (list): List of scopes required for the API.
Returns:
service: The built Google API service instance, or None if authentication fails.
"""
# Load token data from the database
token_data = load_token(team_id, user_id, 'google')
if not token_data:
print(f"No token found for team {team_id}, user {user_id}. Initial authorization required.")
return None
# Fetch client credentials from environment variables
client_id = os.getenv('GOOGLE_CLIENT_ID')
client_secret = os.getenv('GOOGLE_CLIENT_SECRET')
token_uri = os.getenv('GOOGLE_TOKEN_URI', 'https://oauth2.googleapis.com/token')
if not client_id or not client_secret:
print("Google client credentials not found in environment variables.")
return None
# Create Credentials object using token data and client credentials
try:
creds = Credentials(
token=token_data.get('access_token'),
refresh_token=token_data.get('refresh_token'),
token_uri=token_uri,
client_id=client_id,
client_secret=client_secret,
scopes=scopes
)
except ValueError as e:
print(f"Error creating credentials for user {user_id}: {e}")
return None
# Refresh token if expired
if not creds.valid:
if creds.expired and creds.refresh_token:
try:
creds.refresh(Request())
# Save refreshed token data to the database
refreshed_token_data = {
'access_token': creds.token,
'refresh_token': creds.refresh_token,
'expires_at': creds.expiry.timestamp() if creds.expiry else None
}
save_token(team_id, user_id, 'google', refreshed_token_data)
print(f"Token refreshed for user {user_id}.")
except Exception as e:
print(f"Error refreshing token for user {user_id}: {e}")
return None
else:
print(f"Credentials invalid and no refresh token available for user {user_id}.")
return None
# Build and return the Google API service
try:
service = build(api_name, api_version, credentials=creds, static_discovery=False)
return service
except Exception as e:
print(f"Failed to create service instance for {api_name}: {e}")
return None
def construct_google_calendar_client(team_id, user_id):
"""
Constructs a Google Calendar API client for the specified user.
Parameters:
team_id (str): The Slack team ID.
user_id (str): The Slack user ID.
Returns:
service: The Google Calendar API service instance, or None if not authenticated.
"""
API_NAME = 'calendar'
API_VERSION = 'v3'
SCOPES = ['https://www.googleapis.com/auth/calendar']
return create_service(team_id, user_id, API_NAME, API_VERSION, SCOPES) |