#!/usr/bin/env python3 """PiCopy v2 - USB Copy Service mit WiFi-Fallback AP""" import traceback import urllib.request as _urlreq from pathlib import Path from flask import Flask, render_template, send_file, jsonify from picopy.config import VERSION, BASE_DIR, RAW_BASE, log # Absoluter Pfad zum templates/-Verzeichnis, unabhängig vom Arbeitsverzeichnis _HERE = Path(__file__).parent app = Flask(__name__, template_folder=str(_HERE / 'templates')) @app.errorhandler(Exception) def _handle_exception(e): log.error('Unbehandelter Fehler:\n' + traceback.format_exc()) return jsonify(error=str(e)), 500 from routes import register_routes register_routes(app) @app.route('/') def index(): return render_template('index.html', version=VERSION) @app.route('/logo.png') def r_logo(): logo = BASE_DIR / 'PiCopy_Logo.png' if not logo.exists(): try: data = _urlreq.urlopen(f'{RAW_BASE}/PiCopy_Logo.png', timeout=15).read() logo.write_bytes(data) except Exception: return '', 404 return send_file(logo, mimetype='image/png') @app.route('/favicon.ico') def r_favicon(): logo = BASE_DIR / 'PiCopy_Logo.png' if logo.exists(): return send_file(logo, mimetype='image/png') return '', 404 if __name__ == '__main__': import threading from picopy.usb import cleanup_stale_mounts from picopy.state import load_state from picopy.wireguard import wg_update_state, wg_connect, WG_CONF from picopy.copy_engine import usb_monitor from picopy.wifi import wifi_monitor from picopy.wireguard import wg_monitor from picopy.system import update_check_loop from picopy.config import load_cfg # Startprüfung: Template vorhanden? tmpl = _HERE / 'templates' / 'index.html' if not tmpl.exists(): log.error(f'FEHLER: Template nicht gefunden: {tmpl}') else: log.info(f'Template gefunden: {tmpl}') cleanup_stale_mounts() load_state() wg_update_state() threading.Thread(target=usb_monitor, daemon=True).start() threading.Thread(target=wifi_monitor, daemon=True).start() threading.Thread(target=wg_monitor, daemon=True).start() threading.Thread(target=update_check_loop, daemon=True).start() if load_cfg().get('wireguard_auto') and WG_CONF.exists(): threading.Thread(target=wg_connect, daemon=True).start() log.info(f'PiCopy v{VERSION} läuft auf http://0.0.0.0:8080') app.run(host='0.0.0.0', port=8080, debug=False, use_reloader=False)