diff --git a/app.py b/app.py index 2dd6c9c4..01b6e19d 100644 --- a/app.py +++ b/app.py @@ -1,88 +1,59 @@ -# app.py +# app.py (Version mit pyngrok) from flask import Flask, jsonify, request import subprocess import sys import os import logging +from pyngrok import ngrok, conf +from config import Config -# --- Konfiguration --- -# Logging einrichten, um Anfragen und Fehler im Terminal zu sehen logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s') - -# --- Flask App Initialisierung --- app = Flask(__name__) -# --- SCRIPT MAP --- -# Dies ist die zentrale "Telefonzentrale". -# Hier definieren wir, welcher 'action'-Befehl vom Google Sheet -# welches lokale Skript mit welchen Argumenten startet. +# SCRIPT MAP bleibt unverändert SCRIPT_MAP = { - "run_duplicate_check": { - "script": "duplicate_checker.py", - "args": [] - }, - "run_reclassify_branches": { - "script": "brancheneinstufung.py", # Passen Sie ggf. auf 'brancheneinstufung2.py' an - "args": ["--mode", "reclassify_branches"] - }, - "run_predict_technicians": { - "script": "brancheneinstufung.py", # Passen Sie ggf. auf 'brancheneinstufung2.py' an - "args": ["--mode", "predict_technicians"] - }, - "run_full_enrichment": { - "script": "brancheneinstufung.py", # Passen Sie ggf. auf 'brancheneinstufung2.py' an - "args": ["--mode", "full_run"] - } - # Hier können in Zukunft einfach weitere Aktionen hinzugefügt werden, - # z.B. für die Generierung von Marketing-Texten. + "run_duplicate_check": {"script": "duplicate_checker.py", "args": []}, + "run_reclassify_branches": {"script": "brancheneinstufung2.py", "args": ["--mode", "reclassify_branches"]}, + "run_predict_technicians": {"script": "brancheneinstufung2.py", "args": ["--mode", "predict_technicians"]}, } +def setup_ngrok(): + """Konfiguriert und startet den ngrok-Tunnel.""" + try: + authtoken = os.environ.get("NGROK_AUTHTOKEN") + if not authtoken: + if os.path.exists("ngrok_authtoken.txt"): + with open("ngrok_authtoken.txt", "r") as f: authtoken = f.read().strip() + + if not authtoken: + logging.error("NGROK_AUTHTOKEN nicht gefunden. Tunnel kann nicht gestartet werden.") + return None + + conf.get_default().auth_token = authtoken + # Starte den Tunnel zum Port, auf dem Flask laufen wird (8080) + public_url = ngrok.connect(8080, "http") + logging.info(f"!!! Ngrok-Tunnel gestartet: {public_url} !!!") + logging.info("!!! Bitte diese URL im Google Apps Script eintragen (falls sie sich geändert hat). !!!") + return public_url + except Exception as e: + logging.error(f"Fehler beim Starten von ngrok: {e}") + # Beende das Programm, wenn ngrok nicht starten kann + sys.exit(1) @app.route('/run-script', methods=['POST']) def run_script(): - """ - Ein universeller Endpunkt, der verschiedene Skripte basierend - auf einer 'action'-ID im Request starten kann. - """ - try: - data = request.get_json() - if not data: - raise ValueError("Keine JSON-Daten im Request gefunden.") - - action = data.get('action') - - if not action or action not in SCRIPT_MAP: - logging.warning(f"Ungültige oder fehlende Aktion empfangen: {action}") - return jsonify({"status": "error", "message": "Ungültige oder fehlende Aktion."}), 400 - - script_config = SCRIPT_MAP[action] - script_name = script_config["script"] - script_args = script_config["args"] - - # Sicherheitsprüfung: Existiert das Skript? - if not os.path.exists(script_name): - logging.error(f"Skript '{script_name}' für Aktion '{action}' nicht gefunden.") - return jsonify({"status": "error", "message": f"Server-Fehler: Skript '{script_name}' nicht gefunden."}), 500 - - logging.info(f"Aktion '{action}' empfangen. Starte Skript: '{script_name}' mit Argumenten: {script_args}") - - # Stellt sicher, dass der gleiche Python-Interpreter verwendet wird - python_executable = sys.executable - - command = [python_executable, script_name] + script_args - - # Popen startet den Prozess im Hintergrund und kehrt sofort zurück. - # Das verhindert, dass Google Sheets auf das Ende des Skripts wartet und einen Timeout bekommt. - subprocess.Popen(command) - - return jsonify({"status": "success", "message": f"Aktion '{action}' wurde erfolgreich auf dem Server gestartet."}), 200 - - except Exception as e: - logging.error(f"Ein Fehler ist in der run_script-Route aufgetreten: {e}") - return jsonify({"status": "error", "message": f"Server-Fehler: {str(e)}"}), 500 - + # ... (Ihre run_script Logik bleibt unverändert) ... + data = request.get_json() + action = data.get('action') + if not action or action not in SCRIPT_MAP: + return jsonify({"status": "error", "message": "Ungültige Aktion."}), 400 + script_config = SCRIPT_MAP[action] + command = [sys.executable, script_config["script"]] + script_config["args"] + subprocess.Popen(command) + return jsonify({"status": "success", "message": f"Aktion '{action}' gestartet."}), 200 if __name__ == '__main__': - # Startet den Server, erreichbar im lokalen Netzwerk auf Port 8080 - # um Konflikte mit Synology DSM zu vermeiden. + # Starte zuerst ngrok + setup_ngrok() + # Starte dann den Flask-Server app.run(host='0.0.0.0', port=8080) \ No newline at end of file