abdulsalam2121
Refactor default settings in load_saved_settings to remove environment variable dependencies
38a89cd | 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 | |
| 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 = { | |
| "username": "", | |
| "password": "", | |
| "studio": "", | |
| "min_price": 6.0, | |
| } | |
| if not CONFIG_PATH.exists(): | |
| return default_settings | |
| try: | |
| data = json.loads(CONFIG_PATH.read_text(encoding="utf-8")) | |
| return { | |
| "username": data.get("username", default_settings["username"]), | |
| "password": data.get("password", default_settings["password"]), | |
| "studio": data.get("studio", default_settings["studio"]), | |
| "min_price": data.get("min_price", default_settings["min_price"]), | |
| } | |
| except Exception: | |
| return default_settings | |
| def save_settings(payload: Dict[str, Any]) -> None: | |
| data = { | |
| "username": payload.get("username", ""), | |
| "password": payload.get("password", ""), | |
| "studio": payload.get("studio", ""), | |
| "min_price": payload.get("min_price", 6.0), | |
| } | |
| CONFIG_PATH.write_text(json.dumps(data, indent=2), encoding="utf-8") | |
| def index(): | |
| return render_template("index.html", settings=load_saved_settings()) | |
| def start(): | |
| payload = request.get_json(silent=True) or {} | |
| username = str(payload.get("username", "")).strip() | |
| password = str(payload.get("password", "")) | |
| studio = str(payload.get("studio", "")).strip() | |
| min_price = payload.get("min_price", "") | |
| if not username or not password or not studio: | |
| return jsonify({"ok": False, "error": "Username, password, and studio are required"}), 400 | |
| try: | |
| min_price_value = float(min_price) | |
| except Exception: | |
| return jsonify({"ok": False, "error": "Minimum price must be numeric"}), 400 | |
| result = controller.start(username=username, password=password, studio=studio, min_price=min_price_value) | |
| status_code = 200 if result.get("ok") else 400 | |
| return jsonify(result), status_code | |
| def stop(): | |
| return jsonify(controller.stop()) | |
| def status(): | |
| return jsonify(controller.snapshot()) | |
| def screenshot_route(): | |
| # Use absolute path to logs directory (project root) | |
| logs_dir = ROOT_DIR / "logs" | |
| latest = logs_dir / "screenshot_latest.png" | |
| # normalize | |
| 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(): | |
| # List what's in the logs directory for debugging | |
| 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) | |
| def download(): | |
| snapshot = controller.snapshot() | |
| csv_path_raw = snapshot.get("last_csv_path") or str(ROOT_DIR / "exports" / "latest.csv") | |
| path = Path(csv_path_raw) | |
| # Normalize relative paths after project restructuring. | |
| if not path.is_absolute(): | |
| candidates = [ | |
| ROOT_DIR / path, | |
| APP_DIR / path, | |
| Path.cwd() / path, | |
| ] | |
| resolved = next((p for p in candidates if p.exists()), None) | |
| path = resolved or (ROOT_DIR / "exports" / "latest.csv") | |
| path = path.resolve() | |
| if not path.exists() or not path.is_file(): | |
| return jsonify({"ok": False, "error": "No CSV file is available yet"}), 404 | |
| try: | |
| return send_file(str(path), as_attachment=True, download_name=path.name, mimetype="text/csv") | |
| except Exception as exc: | |
| logging.exception("Download failed") | |
| return jsonify({"ok": False, "error": f"Download failed: {exc}"}), 500 | |
| def save_settings_route(): | |
| payload = request.get_json(silent=True) or {} | |
| username = str(payload.get("username", "")).strip() | |
| password = str(payload.get("password", "")) | |
| studio = str(payload.get("studio", "")).strip() | |
| min_price = payload.get("min_price", 6.0) | |
| try: | |
| min_price_value = float(min_price) | |
| except Exception: | |
| return jsonify({"ok": False, "error": "Minimum price must be numeric"}), 400 | |
| save_settings({ | |
| "username": username, | |
| "password": password, | |
| "studio": studio, | |
| "min_price": min_price_value, | |
| }) | |
| 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) | |