Files
Brancheneinstufung2/app.py
2025-08-18 09:45:15 +00:00

120 lines
4.7 KiB
Python

# app.py (v2.0 - Autark & Transparent)
from flask import Flask, jsonify, request, render_template_string
import subprocess
import sys
import os
import logging
import uuid
import json
from datetime import datetime
from pyngrok import ngrok, conf
from config import Config
# --- Konfiguration ---
logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
app = Flask(__name__)
# Verzeichnis für Statusdateien der laufenden Jobs
STATUS_DIR = "job_status"
os.makedirs(STATUS_DIR, exist_ok=True)
# SCRIPT MAP (Passen Sie hier bei Bedarf die Skriptnamen an, z.B. auf brancheneinstufung2.py)
SCRIPT_MAP = {
"run_duplicate_check": {"script": "duplicate_checker.py", "args": []},
"run_reclassify_branches": {"script": "brancheneinstufung.py", "args": ["--mode", "reclassify_branches"]},
"run_predict_technicians": {"script": "brancheneinstufung.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
public_url = ngrok.connect(8080, "http")
logging.info(f"!!! Ngrok-Tunnel gestartet: {public_url} !!!")
logging.info("!!! Bitte diese URL im Google Apps Script eintragen. !!!")
return public_url
except Exception as e:
logging.error(f"Fehler beim Starten von ngrok: {e}")
sys.exit(1)
@app.route('/run-script', methods=['POST'])
def run_script():
"""
Startet ein Skript als Hintergrundprozess.
NEU: Leitet die Ausgabe des Skripts in eine dedizierte Log-Datei um.
"""
action = "unknown"
try:
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]
script_name = script_config["script"]
script_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), script_name)
if not os.path.exists(script_path):
logging.error(f"Skript '{script_path}' nicht gefunden.")
return jsonify({"status": "error", "message": f"Server-Fehler: Skript nicht gefunden."}), 500
logging.info(f"Aktion '{action}' empfangen. Starte Skript: '{script_name}'...")
python_executable = sys.executable
command = [python_executable, script_path] + script_config["args"]
script_dir = os.path.dirname(os.path.abspath(__file__))
# NEU: Dedizierte Log-Datei für den Subprozess erstellen
log_dir = os.path.join(script_dir, "Log")
os.makedirs(log_dir, exist_ok=True)
timestamp = datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
process_log_path = os.path.join(log_dir, f"{timestamp}_{action}.log")
logging.info(f"Die Ausgabe des Skripts wird in '{process_log_path}' protokolliert.")
with open(process_log_path, 'w') as log_file:
subprocess.Popen(
command,
cwd=script_dir,
stdout=log_file,
stderr=log_file
)
return jsonify({"status": "success", "message": f"Aktion '{action}' wurde erfolgreich gestartet. Details siehe Log-Datei."}), 200
except Exception as e:
logging.error(f"Kritischer Fehler in der run_script-Route bei Aktion '{action}': {e}", exc_info=True)
return jsonify({"status": "error", "message": f"Server-Fehler: {str(e)}"}), 500
@app.route('/get-status', methods=['GET'])
def get_status():
"""Liest alle Job-Status-Dateien und gibt den aktuellen Stand zurück."""
all_statuses = []
for filename in os.listdir(STATUS_DIR):
if filename.endswith(".json"):
try:
with open(os.path.join(STATUS_DIR, filename), 'r') as f:
status_data = json.load(f)
status_data['job_id'] = filename.replace('.json', '')
all_statuses.append(status_data)
except Exception as e:
logging.warning(f"Konnte Statusdatei {filename} nicht lesen: {e}")
# Sortiere nach Startzeit, neuester Job zuerst
all_statuses.sort(key=lambda x: x.get('start_time', ''), reverse=True)
return jsonify(all_statuses)
if __name__ == '__main__':
setup_ngrok()
app.run(host='0.0.0.0', port=8080)