Spaces:
No application file
No application file
| from slack_sdk.errors import SlackApiError | |
| import os | |
| from dotenv import load_dotenv | |
| from slack_sdk import WebClient | |
| import sqlite3 | |
| import json | |
| import psycopg2 | |
| import logging | |
| from datetime import datetime | |
| # Load environment variables | |
| load_dotenv() | |
| # Slack credentials | |
| SLACK_BOT_TOKEN = os.environ["SLACK_BOT_TOKEN"] | |
| # Initialize the Slack client | |
| client = WebClient(token=SLACK_BOT_TOKEN) | |
| logger = logging.getLogger(__name__) | |
| def load_preferences(team_id, user_id): | |
| with preferences_cache_lock: | |
| if (team_id, user_id) in preferences_cache: | |
| return preferences_cache[(team_id, user_id)] | |
| try: | |
| conn = psycopg2.connect(os.getenv('DATABASE_URL')) | |
| cur = conn.cursor() | |
| cur.execute('SELECT zoom_config, calendar_tool FROM Preferences WHERE team_id = %s AND user_id = %s', (team_id, user_id)) | |
| row = cur.fetchone() | |
| if row: | |
| zoom_config, calendar_tool = row | |
| # For jsonb, zoom_config is already a dict; no json.loads needed | |
| preferences = { | |
| "zoom_config": zoom_config if zoom_config else {"mode": "manual", "link": None}, | |
| "calendar_tool": calendar_tool or "none" | |
| } | |
| else: | |
| preferences = {"zoom_config": {"mode": "manual", "link": None}, "calendar_tool": "none"} | |
| cur.close() | |
| conn.close() | |
| except Exception as e: | |
| logger.error(f"Failed to load preferences for team {team_id}, user {user_id}: {e}") | |
| preferences = {"zoom_config": {"mode": "manual", "link": None}, "calendar_tool": "none"} | |
| with preferences_cache_lock: | |
| preferences_cache[(team_id, user_id)] = preferences | |
| return preferences | |
| from threading import Lock | |
| user_cache = {} | |
| preferences_cache = {} | |
| preferences_cache_lock = Lock() | |
| user_cache_lock = Lock() # Example threading lock for cache | |
| owner_id_cache = {} | |
| owner_id_lock = Lock() | |
| def initialize_workspace_cache(client, team_id): | |
| conn = psycopg2.connect(os.getenv('DATABASE_URL')) | |
| cur = conn.cursor() | |
| cur.execute('SELECT MAX(last_updated) FROM Users WHERE team_id = %s', (team_id,)) | |
| last_updated_row = cur.fetchone() | |
| last_updated = last_updated_row[0] if last_updated_row and last_updated_row[0] else None | |
| # Check if cache is fresh (e.g., less than 24 hours old) | |
| if last_updated and (datetime.now() - last_updated).total_seconds() < 86400: | |
| cur.execute('SELECT user_id, real_name, email, name, is_owner, workspace_name FROM Users WHERE team_id = %s', (team_id,)) | |
| rows = cur.fetchall() | |
| new_cache = {row[0]: {"real_name": row[1], "email": row[2], "name": row[3], "is_owner": row[4], "workspace_name": row[5]} for row in rows} | |
| with user_cache_lock: | |
| user_cache[team_id] = new_cache | |
| with owner_id_lock: | |
| owner_id_cache[team_id] = next((user_id for user_id, data in new_cache.items() if data['is_owner']), None) | |
| else: | |
| # Fetch user data from Slack and update database | |
| response = client.users_list() | |
| users = response["members"] | |
| workspace_name = client.team_info()["team"]["name"] # Get workspace name from Slack API | |
| new_cache = {} | |
| for user in users: | |
| user_id = user['id'] | |
| profile = user.get('profile', {}) | |
| real_name = profile.get('real_name', 'Unknown') | |
| name = user.get('name', '') | |
| email = f"{name}@gmail.com" # Placeholder; adjust as needed | |
| is_owner = user.get('is_owner', False) | |
| new_cache[user_id] = {"real_name": real_name, "email": email, "name": name, "is_owner": is_owner, "workspace_name": workspace_name} | |
| cur.execute(''' | |
| INSERT INTO Users (team_id, user_id, workspace_name, real_name, email, name, is_owner, last_updated) | |
| VALUES (%s, %s, %s, %s, %s, %s, %s, %s) | |
| ON CONFLICT (team_id, user_id) DO UPDATE SET | |
| workspace_name = %s, real_name = %s, email = %s, name = %s, is_owner = %s, last_updated = %s | |
| ''', (team_id, user_id, workspace_name, real_name, email, name, is_owner, datetime.now(), | |
| workspace_name, real_name, email, name, is_owner, datetime.now())) | |
| conn.commit() | |
| with user_cache_lock: | |
| user_cache[team_id] = new_cache | |
| with owner_id_lock: | |
| owner_id_cache[team_id] = next((user_id for user_id, data in new_cache.items() if data['is_owner']), None) | |
| cur.close() | |
| conn.close() | |
| def get_workspace_owner_id_client(client ): | |
| """Get the workspace owner's user ID.""" | |
| try: | |
| response = client.users_list() | |
| members = response["members"] | |
| for member in members: | |
| if member.get("is_owner"): | |
| return member["id"] | |
| except SlackApiError as e: | |
| print(f"Error fetching users: {e.response['error']}") | |
| return None | |
| def get_workspace_owner_id(client, team_id): | |
| with owner_id_lock: | |
| if team_id in owner_id_cache and owner_id_cache[team_id]: | |
| return owner_id_cache[team_id] | |
| initialize_workspace_cache(client, team_id) | |
| with owner_id_lock: | |
| return owner_id_cache.get(team_id) | |
| # def get_workspace_owner_id(): | |
| # conn = sqlite3.connect('workspace_cache.db') | |
| # c = conn.cursor() | |
| # c.execute('SELECT user_id FROM workspace_cache WHERE is_owner = 1') | |
| # owner_id = c.fetchone() | |
| # conn.close() | |
| # return owner_id[0] if owner_id else None | |
| owner_id_pref = get_workspace_owner_id_client(client) | |
| def GetAllUsers(): | |
| all_users = {} | |
| try: | |
| response = client.users_list() | |
| print(response) | |
| members = response['members'] | |
| for member in members: | |
| user_id = member['id'] | |
| profile = member.get('profile', {}) | |
| user_name = profile.get('real_name', '') # Use real_name from profile | |
| # Use actual email if available, otherwise construct one from member['name'] | |
| email = profile.get('email', f"{member.get('name', '')}@gmail.com") | |
| print(f"User ID: {user_id}, Name: {user_name}, Email: {email}") | |
| all_users[user_id] = {"Slack Id": user_id, "name": user_name, "email": email} | |
| return all_users | |
| except SlackApiError as e: | |
| print(f"Error fetching users: {e.response['error']}") | |
| return {} | |
| def load_token(team_id, user_id, service): | |
| """ | |
| Load token data from 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'). | |
| Returns: | |
| dict: The token data as a dictionary, or None if not found. | |
| """ | |
| 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() | |
| return 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() | |
| all_users_preload = GetAllUsers() | |
| if all_users_preload: | |
| print("Users Prefection enabled") | |
| # def GetAllUsers(): | |
| # return "" | |
| # all_users_preload = "" | |
| # owner_id_pref = "" |