import sqlite3 import os import json import requests from dotenv import load_dotenv load_dotenv(override=True) DB_FILE = "marketing_matrix.db" GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") NOTION_API_KEY = os.getenv("NOTION_API_KEY") NOTION_DB_INDUSTRIES = "2ec88f4285448014ab38ea664b4c2b81" # --- MAPPINGS --- # SuperOffice ID -> Notion Vertical Name VERTICAL_MAP = { 23: "Logistics - Warehouse" } # SuperOffice ID -> Persona Name & Pains (aus unserer Definition) ROLE_MAP = { 19: {"name": "Operativer Entscheider", "pains": "Zuverlässigkeit, einfache Bedienbarkeit, Personaleinsatz-Optimierung, minimale Störungen"}, 20: {"name": "Infrastruktur-Verantwortlicher", "pains": "Technische Machbarkeit, IT-Sicherheit, Integration, Brandschutz"}, 21: {"name": "Wirtschaftlicher Entscheider", "pains": "ROI, Amortisationszeit, Kostenstruktur, Einsparpotenziale"}, 22: {"name": "Innovations-Treiber", "pains": "Wettbewerbsfähigkeit, Modernisierung, Employer Branding, Kundenerlebnis"} } # --- DATABASE SETUP --- def init_db(): conn = sqlite3.connect(DB_FILE) c = conn.cursor() c.execute('''CREATE TABLE IF NOT EXISTS text_blocks (vertical_id INTEGER, role_id INTEGER, subject TEXT, intro TEXT, social_proof TEXT, PRIMARY KEY (vertical_id, role_id))''') conn.commit() conn.close() print("✅ Database initialized.") # --- NOTION FETCHER --- def get_vertical_pains_gains(vertical_name): url = f"https://api.notion.com/v1/databases/{NOTION_DB_INDUSTRIES}/query" headers = { "Authorization": f"Bearer {NOTION_API_KEY}", "Notion-Version": "2022-06-28", "Content-Type": "application/json" } payload = { "filter": { "property": "Vertical", "title": {"contains": vertical_name} } } resp = requests.post(url, headers=headers, json=payload) if resp.status_code == 200: results = resp.json().get("results", []) if results: props = results[0]['properties'] pains = props.get('Pains', {}).get('rich_text', []) gains = props.get('Gains', {}).get('rich_text', []) return { "pains": pains[0]['plain_text'] if pains else "", "gains": gains[0]['plain_text'] if gains else "" } print(f"⚠️ Warning: No data found for {vertical_name}") return {"pains": "N/A", "gains": "N/A"} # --- GEMINI GENERATOR --- def generate_text(vertical_name, v_data, role_id, role_data): url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key={GEMINI_API_KEY}" prompt = f""" Du bist ein B2B-Copywriter. Erstelle 3 Textbausteine für eine Cold-Outreach E-Mail. KONTEXT: Branche: {vertical_name} Branchen-Pains: {v_data['pains']} Lösung-Gains: {v_data['gains']} Rolle: {role_data['name']} Rollen-Pains: {role_data['pains']} AUFGABE: 1. Subject: Betreffzeile (max 40 Zeichen!). Knackig, Pain-bezogen. 2. Intro: Einleitungssatz (max 40 Zeichen!). Brücke Pain -> Lösung. 3. SocialProof: Referenzsatz (max 40 Zeichen!). "Wir arbeiten mit X..." FORMAT (JSON): {{ "Subject": "...", "Intro": "...", "SocialProof": "..." }} """ payload = { "contents": [{"parts": [{"text": prompt}]}], "generationConfig": {"responseMimeType": "application/json"} } try: resp = requests.post(url, json=payload) if resp.status_code == 200: return json.loads(resp.json()['candidates'][0]['content']['parts'][0]['text']) except Exception as e: print(f"Gemini Error: {e}") return None # --- MAIN --- def run_matrix(): init_db() conn = sqlite3.connect(DB_FILE) c = conn.cursor() # Iterate Verticals for v_id, v_name in VERTICAL_MAP.items(): print(f"\nProcessing Vertical: {v_name} (ID: {v_id})") v_data = get_vertical_pains_gains(v_name) # Iterate Roles for r_id, r_data in ROLE_MAP.items(): print(f" > Generating for Role: {r_data['name']} (ID: {r_id})...", end="", flush=True) # Check if exists (optional: skip if exists) # ... text_block = generate_text(v_name, v_data, r_id, r_data) if text_block: # Robustness: Handle list return from Gemini if isinstance(text_block, list): if len(text_block) > 0 and isinstance(text_block[0], dict): text_block = text_block[0] # Take first item if list of dicts else: print(" ❌ Failed (Unexpected JSON format: List without dicts).") continue # Cut to 40 chars hard limit (Safety) subj = text_block.get("Subject", "")[:40] intro = text_block.get("Intro", "Intro")[:40] # Fallback key name check if "Introduction_Textonly" in text_block: intro = text_block["Introduction_Textonly"][:40] proof = text_block.get("SocialProof", "")[:40] if "Industry_References_Textonly" in text_block: proof = text_block["Industry_References_Textonly"][:40] c.execute("INSERT OR REPLACE INTO text_blocks VALUES (?, ?, ?, ?, ?)", (v_id, r_id, subj, intro, proof)) conn.commit() print(" ✅ Done.") else: print(" ❌ Failed.") conn.close() print("\nMatrix generation complete.") if __name__ == "__main__": run_matrix()