import requests import logging from auth_handler import AuthHandler logger = logging.getLogger(__name__) class SuperOfficeClient: """ A client for interacting with the SuperOffice REST API using OAuth 2.0 Bearer tokens. """ def __init__(self, auth_handler: AuthHandler): self.auth_handler = auth_handler self.session = requests.Session() # Mapping for UDF fields (These are typical technical names, but might need adjustment) self.udf_mapping = { "robotics_potential": "x_robotics_potential", "industry": "x_ai_industry", "summary": "x_ai_summary", "last_update": "x_ai_last_update", "status": "x_ai_status" } # Mapping for list values (Explorer -> SO ID) self.potential_id_map = { "High": 1, "Medium": 2, "Low": 3, "None": 4 } def _get_headers(self): """Returns the authorization headers with Bearer token.""" access_token, _ = self.auth_handler.get_ticket() return { 'Authorization': f'Bearer {access_token}', 'Accept': 'application/json', 'Content-Type': 'application/json' } def _get_url(self, path): """Constructs the full URL for a given API path.""" _, webapi_url = self.auth_handler.get_ticket() base = webapi_url.rstrip('/') p = path.lstrip('/') return f"{base}/api/{p}" def test_connection(self): """Tests the connection by fetching the current user.""" url = self._get_url("v1/User/currentPrincipal") try: resp = self.session.get(url, headers=self._get_headers()) resp.raise_for_status() return resp.json() except Exception as e: logger.error(f"Connection test failed: {e}") if hasattr(e, 'response') and e.response is not None: logger.error(f"Response: {e.response.text}") return None def find_contact_by_criteria(self, name=None, url=None, org_nr=None): """Searches for a contact by OrgNr, URL, or Name.""" filters = [] if org_nr: filters.append(f"orgNr eq '{org_nr}'") if url: filters.append(f"urlAddress eq '{url}'") if not filters and name: filters.append(f"name contains '{name}'") if not filters: return None query = " and ".join(filters) path = f"v1/Contact?$filter={query}" try: full_url = self._get_url(path) resp = self.session.get(full_url, headers=self._get_headers()) resp.raise_for_status() data = resp.json() results = data.get("value", []) if results: logger.info(f"Found {len(results)} matching contacts.") return results[0] return None except Exception as e: logger.error(f"Error searching for contact: {e}") return None