import requests import json # ————————————— Environment / Credentials ————————————— TWENTY_API_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJmY2UyYjc4OS1iY2Y4LTQzMjAtYjEyZS0yMjUyZDZkNzhlZjUiLCJ0eXBlIjoiQVBJX0tFWSIsIndvcmtzcGFjZUlkIjoiZmNlMmI3ODktYmNmOC00MzIwLWIxMmUtMjI1MmQ2ZDc4ZWY1IiwiaWF0IjoxNzUwODU4OTI4LCJleHAiOjQ5MDQ0NTg5MjcsImp0aSI6ImNiOTcxMjEyLWExYjAtNGU5NS1hYjI5LWU3YjdiN2E4YWUwMyJ9.mujCJqNnnk0xcQ0VP8m9uLzzXDtjH9AGi0RF2I8VXHA" TWENTY_API_BASE = "https://crm.toothfairyai.com/rest" ZAMMAD_URL = "https://zammad.toothfairyai.com" ZAMMAD_TOKEN = "Ljej6w4vyEp4P4ES95Fi8bxL4Yj6h1G5y7SXMnWnx-EFKDPE6q3wkMdWXSKHy062" ZAMMAD_GROUP = "Users" GRAPH_TENANT_ID = "3ef5b73c-24f4-4f88-b1dd-c136f2ceaf1f" GRAPH_CLIENT_ID = "6a426d19-7f5b-4ab3-9fe8-b6b457f3375b" GRAPH_CLIENT_SECRET = "Vpu8Q~z4qFxIcFDIWM664bcxN5KU1PgDMk91kaNm" GRAPH_FROM_ADDRESS = "support@toothfairyai.com" CUSTOMER_REPLY_SUBJECT = "Thanks for contacting ToothFairyAI" SALES_EMAIL = "daniel.grozdanovic@icloud.com" SUPPORT_EMAIL = "daniel.grozdanovic@toothfairyai.com" # ————————————— Helpers ————————————— def is_business_opportunity(text): keywords = ["partner", "quote", "enterprise", "demo", "pricing", "ai", "onboarding"] return any(kw in text.lower() for kw in keywords) def push_to_twenty(sub): url = f"{TWENTY_API_BASE}/people" headers = { "Authorization": f"Bearer {TWENTY_API_KEY}", "Content-Type": "application/json" } payload = { "name": { "firstName": sub["first_name"], "lastName": sub["last_name"] }, "position": "first", "emails": { "primaryEmail": sub["email"], "additionalEmails": [] } } res = requests.post(url, headers=headers, json=payload) res.raise_for_status() return res.json()["data"]["createPerson"]["id"] def create_zammad_ticket(submission, is_lead): import json url = f"{ZAMMAD_URL}/api/v1/tickets" headers = { "Authorization": f"Token token={ZAMMAD_TOKEN}", "Content-Type": "application/json" } name = f"{submission['first_name']} {submission['last_name']}".strip() ticket_title = f"{'Sales' if is_lead else 'Other'}: {name}" message = submission["message"] real_email = submission["email"] customer = "support@toothfairyai.com" # hardcoded Zammad user article = { "subject": ticket_title, "body": f"Name: {name}\nEmail: {real_email}\n\nMessage:\n{message}", "note": message, "type": "note", # ✅ NOT "email" "internal": False } payload = { "title": ticket_title, "group": ZAMMAD_GROUP, "customer": customer, "article": article } res = requests.post(url, headers=headers, json=payload) if res.status_code not in (200, 201): print("→ Zammad create-ticket ERROR:", res.status_code, res.text) print("→ Payload was:", json.dumps(payload, indent=2)) res.raise_for_status() return res.json() def tag_zammad_ticket(ticket_id, tag): url = f"{ZAMMAD_URL}/api/v1/tickets/{ticket_id}" headers = { "Authorization": f"Token token={ZAMMAD_TOKEN}", "Content-Type": "application/json" } res = requests.put(url, headers=headers, json={"tags": [tag]}) res.raise_for_status() return res.json() def get_graph_token(): url = f"https://login.microsoftonline.com/{GRAPH_TENANT_ID}/oauth2/v2.0/token" data = { "client_id": GRAPH_CLIENT_ID, "client_secret": GRAPH_CLIENT_SECRET, "grant_type": "client_credentials", "scope": "https://graph.microsoft.com/.default" } headers = {"Content-Type": "application/x-www-form-urlencoded"} res = requests.post(url, data=data, headers=headers) res.raise_for_status() return res.json()["access_token"] def send_email(to, subject, body): token = get_graph_token() url = f"https://graph.microsoft.com/v1.0/users/{GRAPH_FROM_ADDRESS}/sendMail" headers = { "Authorization": f"Bearer {token}", "Content-Type": "application/json" } payload = { "message": { "subject": subject, "body": { "contentType": "Text", "content": body }, "toRecipients": [ {"emailAddress": {"address": to}} ] } } res = requests.post(url, headers=headers, json=payload) if res.status_code != 202: print(f"❌ Graph email failed: {res.status_code} {res.text}") # ————————————— Orchestrator ————————————— def process_submission(sub): is_lead = is_business_opportunity(sub["message"]) crm_id = push_to_twenty(sub) tag = "sales" if is_lead else "other" ticket = create_zammad_ticket(sub, is_lead) tag_zammad_ticket(ticket["id"], tag) send_email( to=sub["email"], subject=CUSTOMER_REPLY_SUBJECT, body=( f"Hi {sub['first_name']},\n\n" f"Your ticket “{ticket['title']}” (ID #{ticket['id']}) is in our system—" "we'll be in touch soon.\n\nCheers,\nThe ToothFairyAI Team" ) ) internal_to = SALES_EMAIL if is_lead else SUPPORT_EMAIL internal_subj = "🚀 New Business Lead" if is_lead else "ℹ️ New Inquiry" send_email( to=internal_to, subject=internal_subj, body=( f"CRM ID: {crm_id}\n" f"Zammad Ticket: #{ticket['id']} (Title: {ticket['title']}, Tag: {tag})\n" f"Name: {sub['first_name']} {sub['last_name']}\n" f"Email: {sub['email']}\n" f"Message:\n{sub['message']}" ) )