diff --git a/api.py b/api.py index be7ca63..e37a5a5 100644 --- a/api.py +++ b/api.py @@ -1,33 +1,59 @@ -from flask import Flask, current_app, make_response, request, jsonify, Response +import http +from typing import Dict + +from flask import Flask, Response, jsonify, request from flask_cors import CORS -from typing import Dict, Tuple + import generic_executor -import json app = Flask(__name__) CORS(app) cors = CORS(app, origins=['*']) +def generic_response_maker(status_code: http.HTTPStatus) -> tuple[Response, int]: + match status_code: + case http.HTTPStatus.CREATED: + message = jsonify({'message': 'Creation successful.'}) + case http.HTTPStatus.INTERNAL_SERVER_ERROR: + message = jsonify({'message': 'Internal Server Error.'}) + case http.HTTPStatus.NO_CONTENT: + message = jsonify({'message': 'Deletion successful.'}) + case http.HTTPStatus.ACCEPTED: + message = jsonify({'message': 'Action successful.'}) + case http.HTTPStatus.BAD_REQUEST: + message = jsonify({'message': 'Bad Request, the property you tried to modify is not valid.'}) + case http.HTTPStatus.NOT_FOUND: + message = jsonify({'message': 'Server not found.'}) + case http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE: + message = jsonify({'message': 'Unsupported Media Type / No JSON payload'}) + case http.HTTPStatus.OK: + message = jsonify({'message': 'Success.'}) + case _: + status_code = http.HTTPStatus.BAD_GATEWAY + message = jsonify({'message': 'Bad Gateway.'}) + return message, status_code.value + + @app.route('/AccountCreate', methods=['POST']) -def account_create() -> Response: +def account_create() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) email: str = data.get('email') port: str = data.get('port') print(f'Email received: {email}') print(f'Port received: {port}') - generic_executor.account_create(port) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.account_create(port) + return generic_response_maker(status) @app.route('/ServerCreate', methods=['POST']) -def server_create() -> Response: +def server_create() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') name: str = data.get('name') @@ -35,92 +61,92 @@ def server_create() -> Response: print(f'Port received for server creation: {port}') print(f'Server name: {name}') print(f'Server version: {version}') - generic_executor.server_create(port, name, version) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.server_create(port, name, version) + return generic_response_maker(status) @app.route('/ServerDelete', methods=['POST']) def server_delete() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') name: str = data.get('name') print(f'Port received for server deletion: {port}') print(f'Server name to delete: {name}') - generic_executor.server_delete(port, name) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.server_delete(port, name) + return generic_response_maker(status) @app.route('/AccountDelete', methods=['POST']) def account_delete() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') email: str = data.get('email') print(f'Port received for account deletion: {port}') print(f'Email of account to delete: {email}') - generic_executor.account_delete(port) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.account_delete(port) + return generic_response_maker(status) @app.route('/ServerRun', methods=['POST']) def server_run() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') name: str = data.get('name') print(f'Port received for server launch: {port}') print(f'Server name to launch: {name}') - generic_executor.server_run(port, name) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.server_run(port, name) + return generic_response_maker(status) @app.route('/ServerStop', methods=['POST']) def server_stop() -> tuple[Response, int]: data: Dict[str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') name: str = data.get('name') print(f'Port received for server shutdown: {port}') print(f'Server name to shut down: {name}') - generic_executor.server_stop(port, name) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.server_stop(port, name) + return generic_response_maker(status) @app.route('/UpdateProperty', methods=['POST']) def update_property() -> tuple[Response, int]: data: Dict[str, str, str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') name: str = data.get('name') prop: str = data.get('property') value: str = data.get('value') + status: http.HTTPStatus = generic_executor.update_property(port, name, prop, value) print(f'The server {name} at port {port} changed {prop} to {value}') - generic_executor.update_property(port, name, prop, value) - return jsonify({'message': 'OK'}), 200 + return generic_response_maker(status) @app.route('/Command', methods=['POST']) def command() -> tuple[Response, int]: data: Dict[str, str, str] = request.get_json() if not data: - return jsonify({"error": "No JSON payload"}), 415 + return generic_response_maker(http.HTTPStatus.UNSUPPORTED_MEDIA_TYPE) port: str = data.get('port') _command: str = data.get('command') print(f'Server {port} executed command {_command}') - generic_executor.run_command(port, _command) - return jsonify({'message': 'OK'}), 200 + status: http.HTTPStatus = generic_executor.run_command(port, _command) + return generic_response_maker(status) if __name__ == '__main__': diff --git a/generic_executor.py b/generic_executor.py index 87adc0a..abacf71 100644 --- a/generic_executor.py +++ b/generic_executor.py @@ -1,46 +1,92 @@ from server_mc_manager import MinecraftServerManager +from http import HTTPStatus import file_manager mc_manager: MinecraftServerManager = MinecraftServerManager() -def account_create(port: str) -> bool: - file_manager.create_folder("users/" + port) +def account_create(port: str) -> HTTPStatus: + try: + file_manager.create_folder("users/" + port) + return HTTPStatus.CREATED + except Exception as e: + print(f"Error creating account folder: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def server_create(port: str, name: str, version: str) -> bool: +def server_create(port: str, name: str, version: str) -> HTTPStatus: server_path: str = f"users/{port}/{name}" server_template_path: str = "servers/paper/" + version - file_manager.create_folder(server_path) - file_manager.copy_folder_contents(server_template_path, server_path) - file_manager.copy_folder_contents("servers/shared", server_path) - file_manager.update_server_property(server_path + "/server.properties", "server-port", port) + try: + file_manager.create_folder(server_path) + file_manager.copy_folder_contents(server_template_path, server_path) + file_manager.copy_folder_contents("servers/shared", server_path) + file_manager.update_server_property(server_path + "/server.properties", "server-port", port) + return HTTPStatus.CREATED + except Exception as e: + print(f"Error creating server: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def server_delete(port: str, name: str) -> bool: +def server_delete(port: str, name: str) -> HTTPStatus: server_path: str = f"users/{port}/{name}" - file_manager.delete_non_empty_folder(server_path) + try: + file_manager.delete_non_empty_folder(server_path) + return HTTPStatus.NO_CONTENT + except Exception as e: + print(f"Error deleting server: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def account_delete(port: str) -> bool: - file_manager.delete_non_empty_folder("users/" + port) +def account_delete(port: str) -> HTTPStatus: + try: + file_manager.delete_non_empty_folder("users/" + port) + return HTTPStatus.NO_CONTENT + except Exception as e: + print(f"Error deleting account: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def server_run(port: str, name: str) -> bool: - server_id = mc_manager.start_server(f"users/{port}/{name}") - mc_manager.servers[server_id]['port'] = int(port) +def server_run(port: str, name: str) -> HTTPStatus: + try: + server_id = mc_manager.start_server(f"users/{port}/{name}") + mc_manager.servers[server_id]['port'] = int(port) + return HTTPStatus.ACCEPTED + except Exception as e: + print(f"Error starting server: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def server_stop(port: str, name: str) -> bool: - server_id = mc_manager.get_server_id_by_port(int(port)) - mc_manager.stop_server(server_id) +def server_stop(port: str, name: str) -> HTTPStatus: + try: + server_id = mc_manager.get_server_id_by_port(int(port)) + mc_manager.stop_server(server_id) + return HTTPStatus.ACCEPTED + except Exception as e: + print(f"Error stopping server: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def update_property(port: str, name: str, prop: str, value: str) -> bool: +def update_property(port: str, name: str, prop: str, value: str) -> HTTPStatus: property_file_path: str = f"users/{port}/{name}/server.properties" - file_manager.update_server_property(property_file_path, prop, value) + try: + file_manager.update_server_property(property_file_path, prop, value) + return HTTPStatus.OK + except ValueError as e: + return HTTPStatus.BAD_REQUEST + except Exception as e: + print(f"Unhandled error: {type(e).__name__}, {str(e)}") + return HTTPStatus.INTERNAL_SERVER_ERROR -def run_command(port: str, command: str) -> bool: - server_id = mc_manager.get_server_id_by_port(int(port)) - mc_manager.execute_server_command(server_id, command) +def run_command(port: str, command: str) -> HTTPStatus: + try: + server_id = mc_manager.get_server_id_by_port(int(port)) + if server_id is None: + return HTTPStatus.NOT_FOUND + mc_manager.execute_server_command(server_id, command) + return HTTPStatus.ACCEPTED + except Exception as e: + print(f"Error executing command: {e}") + return HTTPStatus.INTERNAL_SERVER_ERROR +