186 lines
6.0 KiB
Python
186 lines
6.0 KiB
Python
from dotenv import load_dotenv
|
||
import os, requests
|
||
import smtplib
|
||
from email.mime.text import MIMEText
|
||
|
||
load_dotenv()
|
||
|
||
# — DEBUG: confirm env-vars are loading correctly —
|
||
print("→ ZAMMAD_TOKEN:", repr(os.getenv("ZAMMAD_TOKEN")))
|
||
print("→ ZAMMAD_URL: ", repr(os.getenv("ZAMMAD_URL")))
|
||
print("→ TWENTY_API_KEY:", repr(os.getenv("TWENTY_API_KEY")))
|
||
|
||
me = requests.get(
|
||
f"{os.getenv('ZAMMAD_URL')}/api/v1/users/me",
|
||
headers={"Authorization": f"Token token={os.getenv('ZAMMAD_TOKEN')}"}
|
||
)
|
||
print("→ GET /users/me:", me.status_code, me.text)
|
||
|
||
|
||
def is_business_opportunity(text):
|
||
keywords = ["partner", "quote", "enterprise", "demo", "pricing", "ai", "onboarding"]
|
||
return any(word in text.lower() for word in keywords)
|
||
|
||
|
||
def push_to_twenty(submission):
|
||
url = f"{os.getenv('TWENTY_API')}/people"
|
||
headers = {
|
||
"Authorization": f"Bearer {os.getenv('TWENTY_API_KEY')}",
|
||
"Content-Type": "application/json"
|
||
}
|
||
payload = {
|
||
"name": {
|
||
"firstName": submission["first_name"],
|
||
"lastName": submission["last_name"]
|
||
},
|
||
"position": "first",
|
||
"emails": {
|
||
"primaryEmail": submission["email"],
|
||
"additionalEmails": []
|
||
}
|
||
}
|
||
|
||
res = requests.post(url, headers=headers, json=payload)
|
||
if res.status_code not in (200, 201):
|
||
print("→ TwentyCRM error:", res.status_code, res.text)
|
||
res.raise_for_status()
|
||
return res.json()["data"]["createPerson"]["id"]
|
||
|
||
|
||
def create_zammad_ticket(submission, is_lead):
|
||
"""
|
||
Create a new ticket in Zammad (always in 'Users' group).
|
||
Title = "Sales: {Name}" if lead, else "Other: {Name}".
|
||
If is_lead, article is an email to Gabriele & Scott; otherwise a note.
|
||
"""
|
||
ZAMMAD_URL = os.getenv('ZAMMAD_URL')
|
||
ZAMMAD_TOKEN = os.getenv('ZAMMAD_TOKEN')
|
||
ZAMMAD_GROUP = os.getenv('ZAMMAD_GROUP') # must be "Users"
|
||
|
||
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']}"
|
||
ticket_title = f"{'Sales' if is_lead else 'Other'}: {name}"
|
||
customer = submission["email"]
|
||
|
||
if is_lead:
|
||
# Email‐style article
|
||
to_addrs = "daniel.grozdanovic@icloud.com" #gabriele.sanguigno@toothfairyai.com, scott.aquilina@toothfairyai.com
|
||
article_subject = ticket_title
|
||
article_body = (
|
||
f"Name: {name}\n"
|
||
f"Email: {customer}\n\n"
|
||
f"Message:\n{submission['message']}"
|
||
)
|
||
article = {
|
||
"to": to_addrs,
|
||
"subject": article_subject,
|
||
"body": article_body,
|
||
"note": submission["message"],
|
||
"type": "email",
|
||
"internal": False
|
||
}
|
||
else:
|
||
# Internal note
|
||
article = {
|
||
"subject": ticket_title,
|
||
"body": submission["message"],
|
||
"note": submission["message"],
|
||
"type": "note",
|
||
"internal": False
|
||
}
|
||
|
||
payload = {
|
||
"title": ticket_title,
|
||
"customer": customer,
|
||
"group": ZAMMAD_GROUP,
|
||
"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:", payload)
|
||
res.raise_for_status()
|
||
return res.json()
|
||
|
||
|
||
def tag_zammad_ticket(ticket_id, tag):
|
||
url = f"{os.getenv('ZAMMAD_URL')}/api/v1/tickets/{ticket_id}"
|
||
headers = {
|
||
"Authorization": f"Token token={os.getenv('ZAMMAD_TOKEN')}",
|
||
"Content-Type": "application/json"
|
||
}
|
||
res = requests.put(url, headers=headers, json={"tags":[tag]})
|
||
if res.status_code not in (200, 201):
|
||
print("→ Zammad tag-ticket ERROR:", res.status_code, res.text)
|
||
res.raise_for_status()
|
||
return res.json()
|
||
|
||
|
||
def send_email(to, subject, body):
|
||
msg = MIMEText(body)
|
||
msg["From"] = os.getenv("SMTP_USERNAME")
|
||
msg["To"] = to
|
||
msg["Subject"] = subject
|
||
with smtplib.SMTP(os.getenv("SMTP_SERVER"), int(os.getenv("SMTP_PORT"))) as server:
|
||
server.starttls()
|
||
server.login(os.getenv("SMTP_USERNAME"), os.getenv("SMTP_PASSWORD"))
|
||
server.send_message(msg)
|
||
|
||
|
||
def process_submission(submission):
|
||
is_lead = is_business_opportunity(submission["message"])
|
||
crm_id = push_to_twenty(submission)
|
||
tag = "sales" if is_lead else "other"
|
||
|
||
# Capture the full name here so it's available for internal notifications
|
||
name = f"{submission['first_name']} {submission['last_name']}"
|
||
|
||
# 1) Create the ticket with the correct title & article
|
||
ticket = create_zammad_ticket(submission, is_lead)
|
||
|
||
# 2) Tag the ticket
|
||
tag_zammad_ticket(ticket["id"], tag)
|
||
|
||
# 3) Customer confirmation
|
||
send_email(
|
||
to=submission["email"],
|
||
subject=os.getenv("CUSTOMER_REPLY_SUBJECT"),
|
||
body=(
|
||
f"Hi {submission['first_name']},\n\n"
|
||
f"Your ticket “{ticket['title']}” (ID #{ticket['id']}) is in our system—"
|
||
"we'll be in touch soon.\n\n"
|
||
"Cheers,\nThe ToothFairyAI Team"
|
||
)
|
||
)
|
||
|
||
# 4) Internal notification
|
||
internal_to = os.getenv("SALES_EMAIL") if is_lead else os.getenv("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']}, Tags: {tag})\n"
|
||
f"Name: {name}\n"
|
||
f"Email: {submission['email']}\n"
|
||
f"Message: {submission['message']}"
|
||
)
|
||
)
|
||
|
||
|
||
if __name__ == "__main__":
|
||
sample = {
|
||
"first_name": "Joe",
|
||
"last_name": "Smith",
|
||
"email": "support@toothfairyai.com",
|
||
"message": "Interested in a product demo"
|
||
}
|
||
process_submission(sample)
|