import json import os import logging import threading import webbrowser from pathlib import Path from typing import Any, Dict from flask import Flask, jsonify, make_response, render_template, request, send_file from services.run_bot import AutomationController from config import DEFAULT_TARGET_URL APP_DIR = Path(__file__).resolve().parent ROOT_DIR = APP_DIR.parent CONFIG_PATH = APP_DIR / "config.json" logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s: %(message)s") app = Flask( __name__, template_folder=str(APP_DIR / "templates"), static_folder=str(APP_DIR / "static"), static_url_path="/static", ) controller = AutomationController() def load_saved_settings() -> Dict[str, Any]: default_settings = { "target_url": DEFAULT_TARGET_URL, } if not CONFIG_PATH.exists(): return default_settings try: data = json.loads(CONFIG_PATH.read_text(encoding="utf-8")) return { "target_url": data.get("target_url", default_settings["target_url"]), } except Exception: return default_settings def save_settings(payload: Dict[str, Any]) -> None: data = { "target_url": payload.get("target_url", DEFAULT_TARGET_URL), } CONFIG_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") @app.get("/") def index(): return render_template("index.html", settings=load_saved_settings()) @app.post("/start") def start(): result = controller.start(target_url=DEFAULT_TARGET_URL) status_code = 200 if result.get("ok") else 400 return jsonify(result), status_code @app.post("/stop") def stop(): return jsonify(controller.stop()) @app.get("/status") def status(): return jsonify(controller.snapshot()) @app.get("/screenshot") def screenshot_route(): logs_dir = ROOT_DIR / "logs" latest = logs_dir / "screenshot_latest.png" latest = latest.resolve() logging.info(f"Screenshot request: ROOT_DIR={ROOT_DIR}, logs_dir={logs_dir}, latest={latest}, exists={latest.exists()}") if not latest.exists(): if logs_dir.exists(): files = list(logs_dir.glob("*.png")) logging.warning(f"Screenshot not found at {latest}. Files in {logs_dir}: {files}") else: logging.warning(f"Logs directory doesn't exist: {logs_dir}") return ("", 204) try: logging.info(f"Sending screenshot: {latest}") response = make_response(send_file(str(latest), mimetype="image/png")) response.headers["Cache-Control"] = "no-store, no-cache, must-revalidate, max-age=0" response.headers["Pragma"] = "no-cache" response.headers["Expires"] = "0" return response except Exception as e: logging.error(f"Screenshot send failed: {e}") return ("", 500) @app.post("/save-settings") def save_settings_route(): payload = request.get_json(silent=True) or {} target_url = str(payload.get("target_url", DEFAULT_TARGET_URL)).strip() save_settings({ "target_url": target_url, }) return jsonify({"ok": True, "message": "Settings saved"}) if __name__ == "__main__": port = int(os.environ.get("PORT", "5000")) host = "0.0.0.0" if "PORT" in os.environ else "127.0.0.1" if "PORT" not in os.environ: threading.Timer(1.0, lambda: webbrowser.open_new(f"http://localhost:{port}")).start() app.run(host=host, port=port, debug=False, threaded=True)