# Web server component for MacroPad from flask import Flask, render_template_string, request, jsonify, send_file from waitress import serve import logging import os from web_templates import INDEX_HTML class WebServer: def __init__(self, macro_manager, app_dir, port=40000): self.macro_manager = macro_manager self.app_dir = app_dir self.port = port self.app = None def create_app(self): """Create and configure Flask application""" app = Flask(__name__) # Disable Flask's logging except for errors log = logging.getLogger('werkzeug') log.setLevel(logging.ERROR) @app.route('/') def index(): return render_template_string(INDEX_HTML) @app.route('/api/tabs') def get_tabs(): """Get all available tabs (similar to setup_tabs logic)""" tabs = ["All"] # Add tabs based on macro types and custom categories unique_types = set() for macro in self.macro_manager.macros.values(): if macro.get("type"): unique_types.add(macro["type"].title()) # Check for custom category if macro.get("category"): unique_types.add(macro["category"]) for tab_type in sorted(unique_types): if tab_type not in ["All"]: tabs.append(tab_type) return jsonify(tabs) @app.route('/api/macros') def get_macros(): return jsonify(self.macro_manager.macros) @app.route('/api/macros/') def get_macros_by_tab(tab_name): """Filter macros by tab (similar to filter_macros_by_tab logic)""" if tab_name == "All": return jsonify(self.macro_manager.macros) filtered_macros = {} for macro_id, macro in self.macro_manager.macros.items(): # Check type match if macro.get("type", "").title() == tab_name: filtered_macros[macro_id] = macro # Check custom category match elif macro.get("category") == tab_name: filtered_macros[macro_id] = macro return jsonify(filtered_macros) @app.route('/api/image/') def get_image(image_path): try: image_path = os.path.join(self.app_dir, image_path) return send_file(image_path) except Exception as e: return str(e), 404 @app.route('/api/execute', methods=['POST']) def execute_macro(): data = request.get_json() if not data or 'macro_id' not in data: return jsonify({"success": False, "error": "Invalid request"}) macro_id = data['macro_id'] success = self.macro_manager.execute_macro(macro_id) return jsonify({"success": success}) self.app = app return app def run(self): """Run the web server""" if not self.app: self.create_app() try: serve(self.app, host='0.0.0.0', port=self.port, threads=4) except Exception as e: raise e