import httpx from sqlalchemy.orm import Session from uuid import UUID import models import re def normalize_phone_number(phone: str) -> str: """ Convert phone numbers from +972 format to Israeli 0 format Examples: +972501234567 -> 0501234567 +972-50-123-4567 -> 0501234567 972501234567 -> 0501234567 """ if not phone: return phone # Remove all non-digit characters except + cleaned = re.sub(r'[^\d+]', '', phone) # Handle +972 format if cleaned.startswith('+972'): # Remove +972 and add 0 prefix return '0' + cleaned[4:] elif cleaned.startswith('972'): # Remove 972 and add 0 prefix return '0' + cleaned[3:] # If already starts with 0, return as is if cleaned.startswith('0'): return cleaned # If it's a 9-digit number (Israeli mobile without prefix), add 0 if len(cleaned) == 9 and cleaned[0] in '5789': return '0' + cleaned return cleaned async def import_contacts_from_google( access_token: str, db: Session, owner_email: str = None, added_by_user_id: str = None, event_id: str = None ) -> int: """ Import contacts from Google People API Args: access_token: OAuth 2.0 access token from Google db: Database session owner_email: Email of the account importing (stored as owner in DB) added_by_user_id: UUID of the user adding these contacts (required for DB) event_id: Event ID to scope import to (required) Returns: Number of contacts imported """ from uuid import UUID # event_id and added_by_user_id are required if not event_id: raise ValueError("event_id is required for contact imports") if not added_by_user_id: raise ValueError("added_by_user_id is required for contact imports") # Convert to UUID event_uuid = UUID(event_id) user_uuid = UUID(added_by_user_id) headers = { "Authorization": f"Bearer {access_token}" } # Google People API endpoint url = "https://people.googleapis.com/v1/people/me/connections" params = { "personFields": "names,phoneNumbers,emailAddresses", "pageSize": 1000 } imported_count = 0 async with httpx.AsyncClient() as client: response = await client.get(url, headers=headers, params=params) if response.status_code != 200: # Try to parse error details try: error_data = response.json() if 'error' in error_data: error_info = error_data['error'] error_code = error_info.get('code') error_message = error_info.get('message') error_status = error_info.get('status') if error_code == 403 or error_status == 'PERMISSION_DENIED': raise Exception( f"Google People API is not enabled or you don't have permission. " f"Enable the People API in Google Cloud Console." ) else: raise Exception(f"Google API Error: {error_status} - {error_message}") except ValueError: raise Exception(f"Failed to fetch contacts: {response.text}") data = response.json() connections = data.get("connections", []) for connection in connections: # Extract name names = connection.get("names", []) if not names: continue name = names[0] first_name = name.get("givenName", "") last_name = name.get("familyName", "") if not first_name and not last_name: continue # Extract email emails = connection.get("emailAddresses", []) email = emails[0].get("value") if emails else None # Extract phone number phones = connection.get("phoneNumbers", []) phone_number = phones[0].get("value") if phones else None # Normalize phone number to Israeli format (0...) if phone_number: phone_number = normalize_phone_number(phone_number) # Check if contact already exists by email OR phone number existing = None if email: existing = db.query(models.Guest).filter( models.Guest.event_id == event_uuid, models.Guest.email == email ).first() if not existing and phone_number: existing = db.query(models.Guest).filter( models.Guest.event_id == event_uuid, models.Guest.phone_number == phone_number ).first() if existing: # Contact exists - update owner if needed if existing.owner_email != owner_email: existing.owner_email = owner_email db.add(existing) else: # Create new guest guest_data = { "first_name": first_name or "Unknown", "last_name": last_name or "", "email": email, "phone_number": phone_number, "phone": phone_number, # Also set old phone column for backward compat "rsvp_status": "invited", "owner_email": owner_email, "source": "google", "event_id": event_uuid, "added_by_user_id": user_uuid } guest = models.Guest(**guest_data) db.add(guest) imported_count += 1 db.commit() return imported_count