#!/usr/bin/env python3 """Junior AE - Lead Validation & Temperature Optimization""" import json, re, time, urllib.request from datetime import datetime, timedelta from pathlib import Path import ssl ssl._create_default_https_context = ssl._create_unverified_context SCRIPT_DIR = Path(__file__).parent for d in [SCRIPT_DIR / "state", SCRIPT_DIR / "logs"]: d.mkdir(parents=True, exist_ok=True) STATE_FILE = SCRIPT_DIR / "state" / "jae-state.json" LOG_FILE = SCRIPT_DIR / "logs" / f"jae-{datetime.now().strftime('%Y%m%d')}.log" CRM_URL = "https://salesforce.hoaledgeriq.com/rest" CRM_TOKEN = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI5M2FmNGFmNS0zZWQ0LTQ1ZDMtOWE5Zi01MDMzZjc3YTY3MjMiLCJ0eXBlIjoiQVBJX0tFWSIsIndvcmtzcGFjZUlkIjoiOTNhZjRhZjUtM2VkNC00NWQzLTlhOWYtNTAzM2Y3N2E2NzIzIiwiaWF0IjoxNzczMzI4NDQzLCJleHAiOjE4MDQ3ODE2NDIsImp0aSI6IjIwZjEyYzkwLTRkMDctNGJmNi1iMzk3LTZjNmU3MzlmMThjOCJ9.zeM5NvwCSGEcz99m2LYtgb0sVD6WUXcCF7SwonFg930" def log(msg): ts = datetime.now().strftime('%H:%M:%S') print(f"[{ts}] {msg}") with open(LOG_FILE, 'a') as f: f.write(f"[{ts}] {msg}\n") def load_state(): if STATE_FILE.exists(): return json.loads(STATE_FILE.read_text()) return {"last_check": (datetime.now() - timedelta(hours=2)).isoformat(), "processed": 0, "upgraded": 0} def save_state(s): STATE_FILE.write_text(json.dumps(s, indent=2)) def fetch_notes(): try: with urllib.request.urlopen(urllib.request.Request( f"{CRM_URL}/notes?limit=50&order[createdAt]=desc", headers={"Authorization": f"Bearer {CRM_TOKEN}", "Accept": "application/json"} ), timeout=15) as r: return json.loads(r.read().decode()).get('data', {}).get('notes', []) except Exception as e: log(f"Fetch error: {e}") return [] def get_temp(title): t = title.upper() if 'HOT' in t: return 'HOT' if 'WARM' in t: return 'WARM' if 'COLD' in t: return 'COLD' return None def extract_url(body): m = re.search(r'Site:\s*(https?://[^\s\n]+)', str(body)) return m.group(1) if m else None def validate_url(url): if not url: return False, "no_url" try: req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"}, method='HEAD') with urllib.request.urlopen(req, timeout=10, context=ssl._create_unverified_context()) as r: return True, str(r.getcode()) except urllib.error.HTTPError as e: if e.code in [200, 201, 301, 302]: return True, str(e.code) return False, str(e.code) except Exception as e: return False, str(e)[:30] def upgrade(temp): return {'COLD': 'WARM', 'WARM': 'HOT', 'HOT': 'HOT'}.get(temp, temp) def update_note(note_id, body, new_temp, status): try: body = body + f"\n\n**JAE Validated:** {datetime.now().strftime('%Y-%m-%d %H:%M')}\n**New Temp:** {new_temp}\n**Status:** {status}" data = json.dumps({"bodyV2": {"markdown": body}}).encode() urllib.request.urlopen(urllib.request.Request( f"{CRM_URL}/notes/{note_id}", headers={"Authorization": f"Bearer {CRM_TOKEN}", "Content-Type": "application/json"}, data=data, method='PUT' ), timeout=10) return True except Exception as e: log(f"Update failed: {e}") return False def process(): s = load_state() log(f"=== JAE Starting ===") notes = fetch_notes() for note in notes: if '__JAE_Validated__' in note.get('bodyV2', {}).get('markdown', ''): continue title = note.get('title', '') body = note.get('bodyV2', {}).get('markdown', '') note_id = note.get('id') temp = get_temp(title) if not temp: continue url = extract_url(body) is_valid, status = validate_url(url) if is_valid and temp != 'HOT': new_temp = upgrade(temp) log(f"UPGRADE: {title[:40]}... {temp}->{new_temp}") if update_note(note_id, body, new_temp, status): s['upgraded'] += 1 s['processed'] += 1 else: log(f"Verified: {title[:40]}... {temp} (valid={is_valid})") s['processed'] += 1 s['last_check'] = datetime.now().isoformat() save_state(s) log(f"=== Done: {s['processed']} processed, {s['upgraded']} upgraded ===") def main(): while True: process() log("Waiting 3 hours...") time.sleep(10800) if __name__ == "__main__": main()