Slack_App / services.py
ujalaarshad17's picture
first commit
93dae80 verified
# 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)