#!/usr/bin/env python3 """ Willkommensseite-Generierung für CANCOM Simple Signage. ─────────────────────────────────────────────────────── Diese Hilfsdatei sucht anhand von Kundennamen Logos (via OpenAI + Brandfetch), generiert daraus eine HTML-Willkommensseite und fügt sie in die Lobby-Playlist ein. """ import os import json from openai import OpenAI BASE_DIR = os.path.dirname(os.path.abspath(__file__)) MEDIA_DIR = os.path.join(BASE_DIR, "media") WELCOME_FILENAME = "welcome.html" # ------------------------------------------------- # OpenAI-Client # ------------------------------------------------- def get_openai_client(): api_key = os.environ.get("OPENAI_API_KEY") if not api_key: raise ValueError("OPENAI_API_KEY environment variable not set") return OpenAI(api_key=api_key) # ------------------------------------------------- # Brandfetch-Logo-Suche # ------------------------------------------------- def get_brandfetch_logo(domain): """Versucht, ein Firmenlogo über Brandfetch CDN abzurufen. Baut eine direkte CDN-URL: https://cdn.brandfetch.io/{domain}/logo""" print(f"🔍 Generate - Versuche Brandfetch für Domain: {domain}") logo_url = f"https://cdn.brandfetch.io/{domain}/logo?c=1idyd4Tpb2nKaXIIc8T" print(f"✅ Generate - Brandfetch Logo gefunden: {logo_url}") return logo_url # ------------------------------------------------- # Logo-Ermittlung via OpenAI # ------------------------------------------------- def search_customer_logo(customer_name): """ Sucht das Logo eines Kunden über einen zweistufigen Prozess: 1. OpenAI GPT-4 ermittelt die Domain des Unternehmens 2. Brandfetch CDN liefert das Logo zur Domain Gibt die Logo-URL zurück oder None, wenn nichts gefunden wurde. """ print(f"✅ Generate - Suche nach Kundenlogo für: {customer_name}") try: client = get_openai_client() response = client.chat.completions.create( model="gpt-4", messages=[ { "role": "system", "content": """Du bist ein Experte für die Suche nach Domain Namen. Du findest anhand des Firmennamens die richtige Domain dazu Gib nur den Domain Namen zurück, keine weiteren Informationen. FALLBACK: Wenn du kein direkt Aufrufbare Domain findest, antworte mit "FALLBACK".""" }, { "role": "user", "content": f"Finde die Domain für dasUnternehmen: {customer_name}" } ], temperature=0.1, max_tokens=100 ) logo_url = response.choices[0].message.content.strip() print(f"🔍 OpenAI Logo-URL: {logo_url}") if logo_url.upper() == "FALLBACK": logo_url = None if logo_url: brandfetch_url = get_brandfetch_logo(logo_url) if brandfetch_url: return brandfetch_url return None except Exception as e: print(f"❌ Logo search error: {e}") return None # ------------------------------------------------- # HTML-Generierung # ------------------------------------------------- def md_to_html(text): """Wandelt einfaches Markdown in HTML um (fett, kursiv, code, zeilenumbrüche, aufzählungen).""" import re text = re.sub(r'\*\*(.+?)\*\*', r'\1', text) text = re.sub(r'\*(.+?)\*', r'\1', text) text = re.sub(r'`(.+?)`', r'\1', text) lines = text.split('\n') parts = [] in_list = False for line in lines: stripped = line.strip() is_li = stripped.startswith('- ') or stripped.startswith('* ') if is_li: if not in_list: parts.append('') in_list = False if stripped: parts.append(stripped) parts.append('
') if in_list: parts.append('') if parts and parts[-1] == '
': parts.pop() return ''.join(parts) def generate_welcome_html(customer_names, logo_urls, contacts=None, site="stuttgart", background_url=None): """ Generiert den HTML-Code für die Willkommensseite. - Links oben: CANCOM-Logo + "meets" + Kundenlogos - Unter jedem Logo: Ansprechpartner-Kontaktdaten (Landscape) - Portrait: Kontaktdaten links neben den Logos customer_names: Liste der Kundennamen (max. 3) logo_urls: Liste der Logo-URLs (gleiche Reihenfolge) contacts: Liste der Ansprechpartner-Texte (Markdown, optional) site: Standort-Name für die Anzeige background_url: URLs zum Hintergrundbild (None → Standard-Wallpaper) """ site_display = site.capitalize() names_str = ", ".join(customer_names) if customer_names else "Unbekannt" print(f"✅ Generate - Willkommensseite wird generiert für: {names_str} (site: {site})") site_display = site.capitalize() if contacts is None: contacts = [""] * len(customer_names) bg_image = background_url if background_url else "/static/wallpaper.png" cancom_svg = '''''' logo_html = "" for i, (name, url) in enumerate(zip(customer_names, logo_urls)): if url: contact_html = "" if i < len(contacts) and contacts[i]: contact_html = f'''
{md_to_html(contacts[i])}
''' logo_html += f'''
{contact_html}
''' html_content = f""" Willkommen bei CANCOM
meets
{logo_html}
Herzlich Willkommen
in unserer
Niederlassung {site_display}!
""" return html_content # ------------------------------------------------- # Speichern + Playlist-Einfügung # ------------------------------------------------- def save_welcome_page(customer_names, logo_urls, contacts=None, site="stuttgart", background_url=None): """Speichert die generierte Willkommensseite als welcome.html im Lobby-Verzeichnis. contacts: Liste der Ansprechpartner-Texte (Markdown, optional) background_url: Benutzerdefiniertes Hintergrundbild oder None (Standard). Gibt den Dateinamen zurück oder None bei Fehler.""" try: welcome_dir = os.path.join(MEDIA_DIR, site, "lobby") os.makedirs(welcome_dir, exist_ok=True) filepath = os.path.join(os.path.abspath(welcome_dir), WELCOME_FILENAME) html_content = generate_welcome_html(customer_names, logo_urls, contacts=contacts, site=site, background_url=background_url) with open(filepath, "w", encoding="utf-8") as f: f.write(html_content) if os.path.getsize(filepath) == 0: raise IOError("File not written") names_str = ", ".join(customer_names) print(f"✅ Generate - Willkommensseite generiert für: {names_str} (site: {site})") print(f"✅ Generate - Willkommensseite gespeichert in: {filepath}") return WELCOME_FILENAME except Exception as e: print(f"❌ Error saving welcome page: {e}") return None def add_customer_to_lobby_playlist(html_filename, site="stuttgart"): """Fügt die Willkommensseite (welcome.html) an Position 0 in die Lobby-Playlist ein. Entfernt vorher alle vorhandenen welcome.html-Einträge (als String oder Dict). Importiert load_config/save_config aus app.py (kein Zirkelimport).""" try: from app import load_config, save_config config = load_config() sites_cfg = config.setdefault("sites", {}) site_cfg = sites_cfg.setdefault(site, {"screens": {}}) screens = site_cfg.setdefault("screens", {}) lobby = screens.setdefault("lobby", {}) playlist = lobby.setdefault("playlist", []) full_filename = f"{html_filename}" # Alte welcome.html-Einträge entfernen (sowohl String- als auch Dict-Form) playlist[:] = [ item for item in playlist if not ( (isinstance(item, str) and item == full_filename) or (isinstance(item, dict) and item.get("name") == full_filename) ) ] playlist.insert(0, full_filename) save_config(config) print(f"✅ Generate - Willkommensseite in Lobby-Playliste platziert (site: {site})") return True except Exception as e: print(f"❌ Generate - Error adding to playlist: {e}") return False