import sqlite3 import os import json import requests import argparse from dotenv import load_dotenv # --- Configuration & Setup --- load_dotenv(dotenv_path="/home/node/clawd/.env", override=True) DB_PATH = "/home/node/clawd/repos/brancheneinstufung2/company_explorer_local.db" GEMINI_API_KEY = os.getenv("GEMINI_API_KEY") class SniperGenerator: def __init__(self, db_path=DB_PATH): self.db_path = db_path # TODO: Initialize Notion client to get Vertical/Persona data # TODO: Load Marketing Report KPIs into memory def get_lead_data(self, company_id): """Gathers all necessary data for a lead from the local DB.""" conn = sqlite3.connect(self.db_path) conn.row_factory = sqlite3.Row cursor = conn.cursor() cursor.execute("SELECT * FROM companies WHERE id = ?", (company_id,)) company_data = cursor.fetchone() conn.close() if not company_data: return None return dict(company_data) def select_product_and_persona(self, company_data, target_role): """ Implements the '3+1' rule to decide which product to pitch. Placeholder logic - will be replaced with Notion data. """ print(f"🎯 Selecting product for role '{target_role}' in industry '{company_data.get('industry_ai')}'...") # Placeholder for the 3+1 logic # if target_role in ["Wirtschaftl. Entscheider", "Infrastruktur-Verantw."]: # return "Primary" # if target_role == "Innovations-Treiber": # return "Secondary" # if target_role == "Operativer Entscheider": # # Here we would check the "Ops Focus: Secondary?" checkbox from Notion # return "Primary" # Default # For now, we default to the primary product (Cleaning) print("-> Defaulting to 'Primary Product' (Cleaning).") return "Cleaning" def generate_copy(self, company_id, target_role="Wirtschaftl. Entscheider"): """ Generates the 3-sentence sniper copy for a given company and role. """ # 1. Gather Data lead_data = self.get_lead_data(company_id) if not lead_data: return "Error: Company data not found." # 2. Decide on Product (using 3+1 rule) product_to_pitch = self.select_product_and_persona(lead_data, target_role) # 3. Get Social Proof KPIs (from Marketing Report) # Placeholder - using hardcoded values from the report kpis = { "cost_reduction": "10-25%", "time_saving": "20-40%" } # 4. Construct Master Prompt # This is a simplified version for now prompt = f""" Du bist ein Weltklasse B2B-Stratege. Deine Aufgabe ist es, eine 3-Satz-E-Mail-Einleitung im '1,5°-Stil' zu erstellen. **Regeln:** - Satz 1 (Firma): Zeige, dass du das Geschäftsmodell und die zentrale Herausforderung verstanden hast. KEINE ZAHLEN, nur qualitative Größe. - Satz 2 (Persona): Sprich den spezifischen Schmerz der Zielrolle an und verbinde ihn mit dem Produkt '{product_to_pitch}'. - Satz 3 (Social Proof): Untermauere die Lösung mit einem konkreten KPI von Marktbegleitern. **Daten:** - Firma: {lead_data.get('name')} - Branche (KI): {lead_data.get('industry_ai')} - Standort: {lead_data.get('city')} - Rolle: {target_role} - KPI 1 (Kosten): {kpis['cost_reduction']} - KPI 2 (Zeit): {kpis['time_saving']} **Output:** Nur die 3 Sätze. Sonst nichts. """ # 5. Call Gemini API print("📞 Calling Gemini to generate copy...") headers = {"Content-Type": "application/json"} payload = {"contents": [{"parts": [{"text": prompt}]}]} url = f"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent?key={GEMINI_API_KEY}" try: resp = requests.post(url, headers=headers, json=payload, timeout=20) resp.raise_for_status() result = resp.json() copy_text = result['candidates'][0]['content']['parts'][0]['text'].strip() return copy_text except Exception as e: return f"Error during Gemini call: {e}" if __name__ == "__main__": parser = argparse.ArgumentParser(description="Generate sniper copy for a lead.") parser.add_argument("company_id", type=int, help="The Company Explorer ID of the lead.") parser.add_argument("--role", type=str, default="Wirtschaftl. Entscheider", help="The target persona/role.") args = parser.parse_args() sniper = SniperGenerator() final_copy = sniper.generate_copy(args.company_id, args.role) print("\n--- GENERATED SNIPER COPY ---") print(final_copy) print("-----------------------------\n")