#!/usr/bin/env python3 """ One-time Mautic Setup: Create segment, import contacts, create 7 emails. Run once: python scripts/mautic_setup.py All operations in a single process to avoid session expiry. """ import os, sys, json, csv, re from datetime import datetime sys.path.insert(0, "/Users/wmj24/.hermes/mcp-servers/mautic-server") from server import _web_login, _session, BASE, API_TIMEOUT import requests as req from bs4 import BeautifulSoup from urllib.parse import urljoin # ─── Login ────────────────────────────────────────────────── print("Logging into Mautic...") result = _web_login() if not result.get("success"): print(f"Login failed: {result}") sys.exit(1) print("Logged in.") session = req.Session() if _session.get("cookies"): session.cookies.update(_session["cookies"]) csrf_token = _session.get("csrf", "") # ─── 1. Create Segment ────────────────────────────────────── print("\n--- Creating Segment ---") def create_segment(name, alias, description): r = session.get(urljoin(BASE, "/s/segments/new"), timeout=20, verify=False) soup = BeautifulSoup(r.text, "lxml") token_input = soup.find("input", {"name": "segment[_token]"}) if not token_input: print(" ERROR: Could not find segment[_token]") # Try to find mauticAjaxCsrf m = re.search(r"mauticAjaxCsrf\s*=\s*['\"]([^'\"]+)['\"]", r.text) csrf = m.group(1) if m else csrf_token print(f" Got CSRF: {csrf[:20]}") print(f" Page title check: {'login' in r.text.lower()}") return None form_token = token_input.get("value", "") m = re.search(r"mauticAjaxCsrf\s*=\s*['\"]([^'\"]+)['\"]", r.text) ajax_csrf = m.group(1) if m else csrf_token r2 = session.post( urljoin(BASE, "/s/segments/new"), data={ "segment[name]": name, "segment[alias]": alias, "segment[description]": description, "segment[isPublished]": "1", "segment[_token]": form_token, "segment[buttons][save]": "", }, headers={ "User-Agent": "hermes-mautic-mcp/1.0", "X-Requested-With": "XMLHttpRequest", "X-CSRF-Token": ajax_csrf, }, timeout=API_TIMEOUT, verify=False, ) if r2.status_code == 200: # Try to extract segment ID m = re.search(r'/s/segment/(\d+)', r2.text) seg_id = m.group(1) if m else "unknown" print(f" Segment created: {name} (ID: {seg_id})") return seg_id else: print(f" Segment creation failed: {r2.status_code}") print(f" Response: {r2.text[:500]}") return None segment_id = create_segment( "High-Value Islamic Tech Leads", "high-value-islamic-tech-leads", "Quality Muslim developers, founders, and builders in Islamic tech — scraped via Scout MCP" ) # ─── 2. Import Contacts ───────────────────────────────────── print("\n--- Importing Contacts ---") leads_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "quality_leads.json") if not os.path.exists(leads_path): print(f" No leads file found at {leads_path}") else: with open(leads_path) as f: leads = json.load(f) imported = 0 for lead in leads: email = lead.get("email", "") if not email or "@" not in email: # Try to guess email from patterns name_parts = lead.get("full_name", lead.get("username", "")).split() username = lead.get("username", "") domain = lead.get("website", "").replace("https://", "").replace("http://", "").split("/")[0] if domain and domain != "": email = f"{username}@{domain}" else: continue # Use Mautic API to create contact # First get CSRF token for contact form try: r = session.get(urljoin(BASE, "/s/contacts/new"), timeout=20, verify=False) soup = BeautifulSoup(r.text, "lxml") token_input = soup.find("input", {"name": "contact[_token]"}) if token_input: form_token = token_input.get("value", "") m = re.search(r"mauticAjaxCsrf\s*=\s*['\"]([^'\"]+)['\"]", r.text) ajax_csrf = m.group(1) if m else csrf_token r2 = session.post( urljoin(BASE, "/s/contacts/new"), data={ "contact[firstname]": lead.get("firstname", ""), "contact[lastname]": lead.get("lastname", ""), "contact[email]": email, "contact[company]": lead.get("company", ""), "contact[position]": lead.get("position", ""), "contact[website]": lead.get("website", ""), "contact[points]": lead.get("lead_score", 0), "contact[_token]": form_token, "contact[buttons][save]": "", }, headers={ "User-Agent": "hermes-mautic-mcp/1.0", "X-Requested-With": "XMLHttpRequest", "X-CSRF-Token": ajax_csrf, }, timeout=API_TIMEOUT, verify=False, ) if r2.status_code == 200: imported += 1 print(f" Imported: {lead.get('username', email)}") else: print(f" Failed: {lead.get('username', email)} ({r2.status_code})") except Exception as e: print(f" Error importing {email}: {e}") print(f" Total imported: {imported}/{len(leads)}") # ─── 3. Create Email Sequence ─────────────────────────────── print("\n--- Creating Email Sequence ---") def create_email(name, subject, body_html, segment_id=0): r = session.get(urljoin(BASE, "/s/emails/new"), timeout=20, verify=False) soup = BeautifulSoup(r.text, "lxml") token_input = soup.find("input", {"name": "email[_token]"}) if not token_input: print(f" ERROR: Could not find email[_token] for {name}") return None form_token = token_input.get("value", "") m = re.search(r"mauticAjaxCsrf\s*=\s*['\"]([^'\"]+)['\"]", r.text) ajax_csrf = m.group(1) if m else csrf_token r2 = session.post( urljoin(BASE, "/s/emails/new"), data={ "email[name]": name, "email[subject]": subject, "email[customHtml]": body_html, "email[fromName]": "FalahOS", "email[fromAddress]": "hermes@falahos.my", "email[emailType]": "template", "email[isPublished]": "1", "email[_token]": form_token, "email[buttons][save]": "", }, headers={ "User-Agent": "hermes-mautic-mcp/1.0", "X-Requested-With": "XMLHttpRequest", "X-CSRF-Token": ajax_csrf, }, timeout=API_TIMEOUT, verify=False, ) if r2.status_code == 200: print(f" Email created: {name} — '{subject}'") return True else: print(f" Email creation failed for {name}: {r2.status_code}") return False # Email definitions (simplified — full HTML in TRIPWIRE_FUNNEL.md) emails = [ ("Day0-Welcome", "Your Islamic Dev Toolkit is ready 🕌", "
Welcome! Here's your free toolkit...
"), ("Day2-CaseStudy", "How Gading built quran-api (2.5k ⭐)", "Read the story...
"), ("Day5-Tripwire", "Islamic UI Kit for $10", "Stop designing from scratch...
"), ("Day8-Objections", "I'm not a designer — neither were they", "Design isn't your job...
"), ("Day11-Core", "The complete stack — everything you need", "From idea to launched...
"), ("Day14-FAQ", "Questions? (24-hour bonus)", "Quick answers...
"), ("Day18-Enterprise", "Building for an organization?", "Enterprise licensing...
"), ] for name, subject, body in emails: create_email(name, subject, body, segment_id or 0) print("\n--- Setup Complete ---") print("Next steps:") print("1. Verify segment and contacts in Mautic UI") print("2. Verify emails are published") print("3. Set up automation rules in Mautic UI (email → delay → next email)") print("4. Run automation.py daily via cron")