diff --git a/osiris_listener.py b/osiris_listener.py index 2e2a309..6601c65 100644 --- a/osiris_listener.py +++ b/osiris_listener.py @@ -1,11 +1,14 @@ import os import logging +import time +from datetime import datetime from flask import Flask, request, jsonify #from win10toast import ToastNotifier #import asyncio import subprocess import signal import psutil + import telegram from telegram import Update from telegram.ext import Updater, CommandHandler, CallbackContext, MessageHandler, filters @@ -20,25 +23,33 @@ app = Flask(__name__) # Constants #### -# Global list to store process handles -processes = [] -processes_info = [] - # Define the scripts and their parameters -SCRIPTS = { - "start_gameservers_minecraft": [ - # Vanilla (Port 25565) - {"name": "Minecraft Vanilla 1.21", "path": "C:/Users/4lexK/Desktop/GameServers/Minecraft/Vanilla_1-21/start_server.py", "params": ["--java_path", "C:/Program Files/Java/jdk-22/bin", "minecraft_server.1.21"]}, - # The 1.12.2 Pack (SanderPack) (Port 25566) - {"name": "Minecraft The 1.12.2 Pack (SanderPack)", "path": "C:/Users/4lexK/Desktop/GameServers/Minecraft/1-12-2-Pack/start_server.py", "params": ["--java_path", "C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin", 'forge-1.12.2-14.23.5.2860']}, - # GT New Horizon (SanderHorizon) (Port 25567) - {"name": "Minecraft GT New Horizon 2.6.0 (SanderHorizon)", "path": "C:/Users/4lexK/Desktop/GameServers/Minecraft/gt_new_horizons_2.6.0/start_server.py", "params": ["--java_path", "C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin'", 'forge-1.7.10-10.13.4.1614-1.7.10-universal']}, - # rlcraft (SanderHardcore) (Port 25568) - {"name": "Minecraft rlcraft 2.9.3 (SanderHardcore)", "path": "C:/Users/4lexK/Desktop/GameServers/Minecraft/rlcraft/start_server.py", "params": ["--java_path", "C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin'", 'forge-1.12.2-14.23.5.2860']}, - - # Add more scripts and their parameters as needed - ] -} +java_minecraft_servers = [ + { + 'server_name': 'Vanilla 1.21', + 'directory': 'C:/Users/4lexK/Desktop/GameServers/Minecraft/Vanilla_1-21/', + 'command': ['C:/Program Files/Java/jdk-22/bin/java.exe', '-Xmx1024M', '-Xms1024M', '-jar', 'minecraft_server.1.21.jar', '--nogui', '--bonusChest'], + 'wait_time': 30 + }, + { + 'server_name': 'The 1.12.2 Pack (SanderPack)', + 'directory': 'C:/Users/4lexK/Desktop/GameServers/Minecraft/1-12-2-Pack/', + 'command': ['C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin/java.exe', '-Xmx16G', '-XX:+UseG1GC','-Xms4G', '-Dsun.rmi.dgc.server.gcInterval=2147483646', '-XX:+UnlockExperimentalVMOptions', '-XX:G1NewSizePercent=20', '-XX:G1ReservePercent=20', '-XX:MaxGCPauseMillis=50', '-XX:G1HeapRegionSize=32M', '-Dfml.queryResult=confirm', '-Duser.language=en', '-jar', 'forge-1.12.2-14.23.5.2860.jar', '--nogui', '--bonusChest'], + 'wait_time': 30 + }, + { + 'server_name': 'GT New Horizons 2.6.0 (SanderHorizons)', + 'directory': 'C:/Users/4lexK/Desktop/GameServers/Minecraft/gt_new_horizons_2.6.0/', + 'command': ['C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin/java.exe', '-Xmx12G', '-Xms4G', '-XX:+UseStringDeduplication', '-XX:+UseCompressedOops', '-XX:+UseCodeCacheFlushing', '-Dfml.readTimeout=180', '-jar', 'forge-1.7.10-10.13.4.1614-1.7.10-universal.jar', '--nogui', '--bonusChest'], + 'wait_time': 30 + }, + { + 'server_name': 'RLCraft 2.9.3 (SanderHardcore)', + 'directory': 'C:/Users/4lexK/Desktop/GameServers/Minecraft/rlcraft/', + 'command': ['C:/Program Files/OpenLogic/jdk-8.0.412.08-hotspot/bin/java.exe', '-Xmx16G', '-Xms4G', '-jar', 'forge-1.12.2-14.23.5.2860.jar', '--nogui', '--bonusChest'], + 'wait_time': 30 + } +] #### # Telegramm Functions @@ -82,15 +93,12 @@ def read_pid_file(pid_file): except (FileNotFoundError, ValueError): return None -def is_java_process_running(pid): - """Check if a Java process with the given PID is running.""" +def is_java_process(pid): try: - proc = psutil.Process(pid) - if 'java' in proc.name().lower(): - return True - except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess): + p = psutil.Process(pid) + return 'java' in p.name().lower() + except psutil.NoSuchProcess: return False - return False #### # Flask Functions @@ -99,8 +107,6 @@ def is_java_process_running(pid): @app.route('/osiris_execute', methods=['POST']) def execute_script(): logging.info("Commando zur Ausführung erhalten.") - global processes # Declare the global variable - global processes_info data = request.get_json() command = data.get('command') @@ -137,64 +143,77 @@ def execute_script(): case 'start_gameservers_minecraft': logging.info("Received request to start minecraft servers.") #toaster.show_toast("start_gameservers_minecraft", "Starte Minecraft-Server", duration=10) - results = [] - for script_info in SCRIPTS['start_gameservers_minecraft']: - path = script_info["path"] - params = script_info["params"] - script_name = script_info["name"] - command = ['python', path] + params - pid_file = os.path.join(os.path.dirname(path), 'server.pid') - - pid = read_pid_file(pid_file) - if is_java_process_running(pid): - logging.info(f"Script {script_name} is already running.") - results.append({ - "script": path, - "params": params, - "status": "already running" - }) - continue + response_msg = "Folgende Minecraft-Server wurden bearbeitet:" + for server in java_minecraft_servers: + os.chdir(server['directory']) + pid_file = os.path.join(server['directory'], 'server.pid') + log_file = os.path.join(server['directory'], 'logs', f'server_{datetime.now().strftime("%Y%m%d_%H%M%S")}.log') + #wait_time = server['wait_time'] - try: - logging.info(f"Starting script: {command}") - process = subprocess.Popen(command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - psutil_process = psutil.Process(process.pid) - processes.append(psutil_process) - processes_info.append({"process": psutil_process, "name": script_name}) - logging.info(f"Started {script_name} with PID: {psutil_process.pid}") - results.append({ - "script": path, - "params": params, - "pid": psutil_process.pid - }) - except Exception as e: - logging.error(f"Error starting script {path}: {e}") - results.append({ - "script": path, - "params": params, - "error": str(e) - }) - #asyncio.run(send_telegram_message("Minecraft-Server wurden gestartet.")) - return jsonify({"message": "Start der Server wurde veranlasst", "results": results}) + # Create logs directory if it doesn't exist + os.makedirs(os.path.dirname(log_file), exist_ok=True) + + if os.path.exists(pid_file): + with open(pid_file, 'r') as file: + pid = int(file.read().strip()) + if psutil.pid_exists(pid) and is_java_process(pid): + response_msg += f"\nServer {server['server_name']} läuft bereits." + continue + else: + os.remove(pid_file) + + #response_msg += f"Server {server['server_name']} wird gestartet." + with open(log_file, 'w') as log: + process = subprocess.Popen( + server['command'], + cwd=server['directory'], + stdout=log, + stderr=log, + creationflags=subprocess.CREATE_NEW_PROCESS_GROUP if os.name == 'nt' else 0 + ) + #time.sleep(wait_time) + with open(pid_file, 'w') as file: + file.write(str(process.pid)) + response_msg += f"\nServer {server['server_name']} wurde mit PID '{process.pid}' gestartet." + return jsonify({"message": f"{response_msg}"}) #return jsonify({'message': 'Minecraft-Server werden gestartet.'}) case 'stop_gameservers_minecraft': - logging.info("Received request to stop minecraft servers.") - for process in processes: - try: - #toaster.show_toast("stop_gameservers_minecraft", "Stoppe Minecraft-Server", duration=10) - #process.send_signal(signal.SIGINT) - process.terminate() - logging.info(f"Sent SIGINT to process with PID: {process.pid}") - process.wait() - logging.info(f"Process with PID {process.pid} terminated.") - - except Exception as exc: - logging.error(f"Error sending SIGINT to process with PID {process.pid}") - processes = [] # clear process list - processes_info = [] + logging.info("Received request to stop minecraft servers.") + response_msg = "Folgende Minecraft-Server wurden bearbeitet:" + for server in java_minecraft_servers: + pid_file = os.path.join(server['directory'], 'server.pid') + wait_time = server['wait_time'] + flag_delete_pid = False + if os.path.exists(pid_file): + with open(pid_file, 'r') as file: + pid = int(file.read().strip()) + if psutil.pid_exists(pid) and is_java_process(pid): + p = psutil.Process(pid) + if os.name == 'nt': + p.terminate() # Use terminate for Windows + else: + p.send_signal(signal.SIGTERM) + try: + p.wait(timeout=wait_time) + if not psutil.pid_exists(pid): + flag_delete_pid = True + response_msg += f"\nServer {server['server_name']} mit PID {pid} gestoppt." + else: + response_msg += f"\nFehler beim Stoppen des Servers {server['server_name']} mit PID {pid}." + except psutil.TimeoutExpired: + response_msg += f"Timeout während stoppen des Server {server['server_name']} mit PID {pid}." + else: + flag_delete_pid = True + response_msg += f"Stale PID file von Server {server['server_name']} entfernt." + if flag_delete_pid: + os.remove(pid_file) + response_msg += f"PID File gelöscht" + flag_delete_pid = False + else: + response_msg += f"Es existiert kein PID File für Server {server['server_name']}" #asyncio.run(send_telegram_message("Minecraft-Server wurden heruntergefahren.")) - return jsonify({'message': "SIGINT (CTRL-C an alle laufenden Minecraft server gesendet."}) + return jsonify({'message': response_msg}) case 'start_gameservers_dontstarve': try: #toaster.show_toast("start_gameservers_dontstarve", "Starte Dont Starve Together-Server", duration=10) @@ -264,15 +283,21 @@ def status(): @app.route('/status_servers', methods=['GET']) def status_gameservers(): logging.info("Check Status der Server") - global processes_info - running_servers = [] - server_list = [] - for process in processes_info: - running_servers.append(process['name']) - server_list = "\n - ".join(running_servers) + response_msg = "Status Game Server:" + for server in java_minecraft_servers: + pid_file = os.path.join(server['directory'], 'server.pid') + if os.path.exists(pid_file): + with open(pid_file, 'r') as file: + pid = int(file.read().strip()) + if psutil.pid_exists(pid) and is_java_process(pid): + response_msg += f"\nServer {server['server_name']} läuft mit PID {pid}." + else: + response_msg += f"\nServer {server['server_name']} läuft nicht." + else: + response_msg += f"\nKein PID file für Server {server['server_name']} gefunden." #asyncio.run(send_telegram_message(f"Aktuell laufende Server: {server_list}")) - return jsonify({"message": f"Aktuell laufende Server: {server_list}" }) + return jsonify({"message": response_msg }) if __name__ == '__main__':