Files
HOALedgerIQ_Website/agents/sales-lead/integrate.sh
olsch01 5319bcd30b feat: Add Chatwoot Agent Bot prototype and FAQ knowledge base
- Created chatwoot-agent-bot/ with Node.js webhook server
- Bot detects intent (greeting, billing, technical, features, account)
- Auto-responds from FAQ knowledge base or escalates to human
- FAQ-KB.md: Living knowledge base that grows with customer questions
- CHATWOOT-SETUP.md: Complete deployment and configuration guide
- Supports Telegram notifications on escalation
- Bot runs on port 3001, ready for Chatwoot webhook integration
2026-04-01 16:26:05 -04:00

199 lines
7.2 KiB
Bash
Executable File

#!/bin/bash
# Sales Lead CRM Integration Script - v3 (Fixed deduplication)
# Polls website leads endpoint and pushes to Twenty CRM
set -e
WORKSPACE="/Users/claw/.openclaw/workspace/agents/sales-lead"
STATE_FILE="$WORKSPACE/state.json"
LOG_FILE="$WORKSPACE/integration.log"
NOTIFY_FILE="$WORKSPACE/notifications.log"
ADMIN_KEY="K9mP2vL8x4qR7nZ"
TWENTY_BASE="https://salesforce.hoaledgeriq.com/rest"
TWENTY_TOKEN="eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5M2FmNGFmNS0zZWQ0LTQ1ZDMtOWE5Zi01MDMzZjc3YTY3MjMiLCJ0eXBlIjoiQVBJX0tFWSIsIndvcmtzcGFjZUlkIjoiOTNhZjRhZjUtM2VkNC00NWQzLTlhOWYtNTAzM2Y3N2E2NzIzIiwiaWF0IjoxNzczMzI4NDQzLCJleHAiOjE4MDQ3ODE2NDIsImp0aSI6IjIwZjEyYzkwLTRkMDctNGJmNi1iMzk3LTZjNmU3MzlmMThjOCJ9.zeM5NvwCSGEcz99m2LYtgb0sVD6WUXcCF7SwonFg930"
echo "[$(date)] Running CRM integration check" >> "$LOG_FILE"
mkdir -p "$WORKSPACE"
# Initialize state if not exists
if [[ ! -f "$STATE_FILE" ]]; then
echo '{"processed_leads": [], "processed_calc_ids": [], "crm_pushed": {"calc_ids": [], "lead_ids": []}, "last_check": null, "status": "active"}' > "$STATE_FILE"
fi
# Read current state
STATE=$(cat "$STATE_FILE")
PROCESSED_LEADS=$(echo "$STATE" | jq -r '.processed_leads // []')
echo "=== Checking endpoints at $(date) ===" >> "$LOG_FILE"
echo "Already processed leads: $(echo "$PROCESSED_LEADS" | jq -r '. | join(", ")')" >> "$LOG_FILE"
# Fetch leads from API
RESPONSE=$(curl -s -H "x-admin-key: $ADMIN_KEY" "https://www.hoaledgeriq.com/api/leads" 2>&1 || echo "CONNECTION_FAILED")
if [[ "$RESPONSE" == "CONNECTION_FAILED" ]]; then
echo "⚠️ hoaledgeriq.com/api/leads not accessible" >> "$LOG_FILE"
exit 1
fi
if ! echo "$RESPONSE" | jq empty 2>/dev/null; then
echo "⚠️ Invalid response from hoaledgeriq.com" >> "$LOG_FILE"
exit 1
fi
echo "✓ hoaledgeriq.com/api/leads responding" >> "$LOG_FILE"
# Save leads to temp file for processing
LEADS_TEMP=$(mktemp)
echo "$RESPONSE" | jq -r '.leads[]? | @base64' 2>/dev/null > "$LEADS_TEMP"
# Process each lead
NEW_PROCESSED="$PROCESSED_LEADS"
FOUND_COUNT=0
while IFS= read -r encoded; do
[[ -z "$encoded" ]] && continue
item=$(echo "$encoded" | base64 -d)
id=$(echo "$item" | jq -r '.id // empty')
email=$(echo "$item" | jq -r '.email // empty')
[[ -z "$id" || -z "$email" ]] && continue
# Check if already processed
if echo "$NEW_PROCESSED" | jq -e --arg id "$id" 'index($id)' >/dev/null 2>&1; then
echo "Skipping lead $id (already processed)" >> "$LOG_FILE"
continue
fi
echo "🎉 NEW LEAD: id=$id, email=$email" | tee -a "$LOG_FILE" "$NOTIFY_FILE"
# Send Telegram notification via OpenClaw
TG_MSG="🏠 NEW LEAD ALERT
Name: $display_name
Email: $email
Organization: $org_name
State: $state_loc
Role: $role
Units: $unit_count
Beta: $beta_text
Check CRM: salesforce.hoaledgeriq.com"
openclaw message send --text "$TG_MSG" 2>/dev/null || echo "Notification queued"
FOUND_COUNT=$((FOUND_COUNT + 1))
# Extract all fields
first_name=$(echo "$item" | jq -r '.first_name // ""')
last_name=$(echo "$item" | jq -r '.last_name // ""')
org_name=$(echo "$item" | jq -r '.org_name // "N/A"')
state_loc=$(echo "$item" | jq -r '.state // "N/A"')
role=$(echo "$item" | jq -r '.role // "N/A"')
unit_count=$(echo "$item" | jq -r '.unit_count // "N/A"')
beta_interest=$(echo "$item" | jq -r '.beta_interest // 0')
source=$(echo "$item" | jq -r '.source // "unknown"')
created_at=$(echo "$item" | jq -r '.created_at // "N/A"')
display_name="${first_name} ${last_name}"
[[ -z "$first_name" && -z "$last_name" ]] && display_name="Unknown Lead"
# Create Person
person_json="{\"name\":{\"firstName\":\"$first_name\",\"lastName\":\"$last_name\"},\"emails\":{\"primaryEmail\":\"$email\",\"additionalEmails\":[]}}"
person_res=$(curl -s -X POST "$TWENTY_BASE/people" \
-H "Authorization: Bearer $TWENTY_TOKEN" \
-H "Content-Type: application/json" \
-d "$person_json" 2>/dev/null)
person_id=$(echo "$person_res" | jq -r '.data.createPerson.id // empty')
if [[ -n "$person_id" ]]; then
echo "✓ Created Person: $person_id ($display_name)" >> "$LOG_FILE"
else
# Person exists - find by email
all_people=$(curl -s "$TWENTY_BASE/people" -H "Authorization: Bearer $TWENTY_TOKEN")
person_id=$(echo "$all_people" | jq -r --arg em "$email" '.data.people[] | select(.emails.primaryEmail == $em) | .id' | head -1)
[[ -n "$person_id" ]] && echo "✓ Found Person: $person_id ($display_name)" >> "$LOG_FILE"
fi
# Create Note
if [[ -n "$person_id" ]]; then
beta_text="No"
[[ "$beta_interest" == "1" ]] && beta_text="Yes"
# Build note body
note_text="## 🌐 Website Lead Submission
**Name:** $display_name
**Email:** $email
**Organization:** $org_name
**State:** $state_loc
**Role/Position:** $role
**Unit Count:** $unit_count
**Beta Interest:** $beta_text
**Source:** $source
**Submitted:** $created_at
---
*Submitted via website lead form. Review for opportunity qualification.*"
# Escape for JSON
escaped_body=$(echo "$note_text" | jq -Rs .)
note_json="{\"title\":\"🌐 Lead: $display_name | $org_name\",\"bodyV2\":{\"markdown\":"$escaped_body"}}"
note_res=$(curl -s -X POST "$TWENTY_BASE/notes" \
-H "Authorization: Bearer $TWENTY_TOKEN" \
-H "Content-Type: application/json" \
-d "$note_json" 2>/dev/null)
note_id=$(echo "$note_res" | jq -r '.data.createOneNote.id // empty')
if [[ -n "$note_id" ]]; then
echo "✓ Created Note: $note_id ($org_name, $role)" >> "$LOG_FILE"
else
echo "⚠️ Note creation response: $note_res" >> "$LOG_FILE"
fi
fi
# Add to processed list (update in memory and immediately save)
NEW_PROCESSED=$(echo "$NEW_PROCESSED" | jq --arg id "$id" '. + [$id]')
echo "$STATE" | jq --argjson processed "$NEW_PROCESSED" '.processed_leads = $processed' > "$STATE_FILE.tmp" && mv "$STATE_FILE.tmp" "$STATE_FILE"
done < "$LEADS_TEMP"
# Clean up temp file
rm -f "$LEADS_TEMP"
# Update last check timestamp
STATE=$(cat "$STATE_FILE")
echo "$STATE" | jq --arg ts "$(date -u +%Y-%m-%dT%H:%M:%SZ)" '.last_check = $ts' > "$STATE_FILE.tmp" && mv "$STATE_FILE.tmp" "$STATE_FILE"
if [[ $FOUND_COUNT -eq 0 ]]; then
echo "No new leads found" >> "$LOG_FILE"
else
echo "Processed $FOUND_COUNT new leads" >> "$LOG_FILE"
fi
echo "=== Completed at $(date) ===" >> "$LOG_FILE"
echo "" >> "$LOG_FILE"
# Telegram notification function
send_telegram_notification() {
local name="$1"
local email="$2"
local org="$3"
local state="$4"
local role="$5"
local units="$6"
local beta="$7"
curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
-H "Content-Type: application/json" \
-d "{
\"chat_id\": \"${TELEGRAM_CHAT_ID}\",
\"text\": \"🏠 NEW LEAD ALERT\\n\\nName: $name\\nEmail: $email\\nOrganization: $org\\nState: $state\\nRole: $role\\nUnits: $units\\nBeta: $beta\\n\\nCheck CRM for details\",
\"parse_mode\": \"Markdown\"
}" 2>/dev/null || echo "Telegram notification sent"
}