import time import datetime import requests from flask import current_app class WebexManager: def __init__(self, db_collection, client_id, client_secret, redirect_uri, team_id, user_id): self.db = db_collection self.client_id = client_id self.client_secret = client_secret self.redirect_uri = redirect_uri self.team_id = team_id self.user_id = user_id self.base_url = "https://webexapis.com/v1" def save_tokens(self, token_data: dict): """Saves or updates Webex OAuth tokens in MongoDB.""" now = time.time() doc = { "_id": "webex_credentials", "access_token": token_data.get("access_token"), "refresh_token": token_data.get("refresh_token"), "expires_at": now + token_data.get("expires_in", 43200) - 300, # Subtract 5 mins buffer "refresh_token_expires_at": now + token_data.get("refresh_token_expires_in", 7776000), "updated_at": datetime.datetime.now(datetime.timezone.utc).isoformat() } self.db.replace_one({"_id": "webex_credentials"}, doc, upsert=True) return doc def get_access_token(self) -> str: """Retrieves a valid access token from MongoDB, auto-refreshing if expired.""" token_doc = self.db.find_one({"_id": "webex_credentials"}) if not token_doc: raise Exception("No Webex OAuth tokens found. Please complete login at /oauth/login.") # Check if access token is expired if time.time() >= token_doc.get("expires_at", 0): current_app.logger.info("Webex access token expired. Refreshing...") return self.refresh_token(token_doc.get("refresh_token")) return token_doc.get("access_token") def exchange_code(self, code: str) -> dict: """Exchanges OAuth code for access and refresh tokens.""" payload = { "grant_type": "authorization_code", "client_id": self.client_id, "client_secret": self.client_secret, "code": code, "redirect_uri": self.redirect_uri } res = requests.post(f"{self.base_url}/access_token", data=payload) res.raise_for_status() return self.save_tokens(res.json()) def refresh_token(self, refresh_token: str) -> str: """Refreshes the Webex access token using the stored refresh_token.""" payload = { "grant_type": "refresh_token", "client_id": self.client_id, "client_secret": self.client_secret, "refresh_token": refresh_token } res = requests.post(f"{self.base_url}/access_token", data=payload) res.raise_for_status() new_doc = self.save_tokens(res.json()) return new_doc["access_token"] def create_support_room(self, client_name: str, client_email: str) -> str: """Creates a team support room and invites the client and yourself.""" access_token = self.get_access_token() headers = { "Authorization": f"Bearer {access_token}", "Content-Type": "application/json" } # 1. Create room under team room_res = requests.post( f"{self.base_url}/rooms", headers=headers, json={ "title": f"Smartwave Support: {client_name}", "teamId": self.team_id } ) room_res.raise_for_status() room_id = room_res.json()["id"] # 2. Add Client via email (Webex sends invite if user does not exist) if client_email: requests.post( f"{self.base_url}/memberships", headers=headers, json={"roomId": room_id, "personEmail": client_email} ) # 3. Add yourself (WEBEX_NINLUC_ID) if self.user_id: requests.post( f"{self.base_url}/memberships", headers=headers, json={"roomId": room_id, "personId": self.user_id} ) # 4. Optional: Send initial welcome message in the room requests.post( f"{self.base_url}/messages", headers=headers, json={ "roomId": room_id, "text": f"Support room initialized for {client_name}. An agent will be with you shortly." } ) return room_id