from flask import Flask, request, jsonify import os import sqlite3 import hashlib from superoffice_client import SuperOfficeClient # Our new shiny client class app = Flask(__name__) # --- CONFIGURATION --- DB_FILE = "marketing_matrix.db" # UDF ProgIds (from our plan) PROG_ID_CONTACT_VERTICAL = "SuperOffice:5" PROG_ID_PERSON_ROLE = "SuperOffice:3" PROG_ID_CONTACT_CHALLENGE = "SuperOffice:6" PROG_ID_PERSON_SUBJECT = "SuperOffice:5" PROG_ID_PERSON_INTRO = "SuperOffice:6" PROG_ID_PERSON_PROOF = "SuperOffice:7" PROG_ID_PERSON_HASH = "SuperOffice:8" # --- CORE LOGIC --- def get_text_from_matrix(vertical_id, role_id): """Fetches the pre-generated text block from the local SQLite DB.""" conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute("SELECT subject, intro, social_proof FROM text_blocks WHERE vertical_id = ? AND role_id = ?", (vertical_id, role_id)) row = c.fetchone() conn.close() return row if row else (None, None, None) def process_single_person(client: SuperOfficeClient, person_id: int): """Central logic to update marketing copy for a single person.""" print(f"Processing Person ID: {person_id}") person_data = client.get_person(person_id) if not person_data: raise ValueError(f"Person {person_id} not found") contact_id = person_data.get('contact', {}).get('contactId') if not contact_id: raise ValueError("Person is not linked to a Contact") contact_data = client.get_contact(contact_id) if not contact_data: raise ValueError(f"Contact {contact_id} not found") # Extract and clean Vertical and Role IDs vertical_id_raw = contact_data["UserDefinedFields"].get(PROG_ID_CONTACT_VERTICAL, "") role_id_raw = person_data["UserDefinedFields"].get(PROG_ID_PERSON_ROLE, "") if not vertical_id_raw or not role_id_raw: raise ValueError("Vertical or Role ID is not set.") vertical_id = int(vertical_id_raw.replace("[I:", "").replace("]", "")) role_id = int(role_id_raw.replace("[I:", "").replace("]", "")) # Get text from matrix subject, intro, proof = get_text_from_matrix(vertical_id, role_id) if not subject: raise ValueError(f"No text found in matrix for V:{vertical_id}, R:{role_id}") # Generate Hash text_concat = f"{subject}{intro}{proof}" copy_hash = hashlib.md5(text_concat.encode()).hexdigest() # Prepare payloads contact_payload = {PROG_ID_CONTACT_CHALLENGE: intro} person_payload = { PROG_ID_PERSON_SUBJECT: subject, PROG_ID_PERSON_INTRO: intro, PROG_ID_PERSON_PROOF: proof, PROG_ID_PERSON_HASH: copy_hash } # Inject data client.update_udfs("Contact", contact_id, contact_payload) client.update_udfs("Person", person_id, person_payload) return f"Updated Person {person_id} with texts for V:{vertical_id}/R:{role_id}" # --- WEBHOOK ENDPOINTS --- @app.route('/regenerate_for_person', methods=['POST']) def webhook_person(): data = request.get_json() if not data or "person_id" not in data: return jsonify({"error": "Missing person_id"}), 400 try: client = SuperOfficeClient() message = process_single_person(client, data['person_id']) return jsonify({"status": "success", "message": message}), 200 except Exception as e: print(f"❌ Error processing person: {e}") return jsonify({"error": str(e)}), 500 @app.route('/regenerate_for_contact', methods=['POST']) def webhook_contact(): data = request.get_json() if not data or "contact_id" not in data: return jsonify({"error": "Missing contact_id"}), 400 contact_id = data['contact_id'] print(f"Received request to regenerate for all persons in Contact ID: {contact_id}") try: client = SuperOfficeClient() contact = client.get_contact(contact_id) if not contact or not contact.get('persons'): return jsonify({"status": "success", "message": "No persons found for this contact."}), 200 updated_count = 0 for person_summary in contact['persons']: try: process_single_person(client, person_summary['personId']) updated_count += 1 except Exception as e: print(f" - Skipping Person {person_summary.get('personId')}: {e}") return jsonify({"status": "success", "message": f"Processed {updated_count} persons for Contact {contact_id}"}), 200 except Exception as e: print(f"❌ Error processing contact: {e}") return jsonify({"error": str(e)}), 500 if __name__ == '__main__': # For local dev. Use a proper WSGI server (Gunicorn) for production. # Needs pip install Flask app.run(host='0.0.0.0', port=5001, debug=True)