From a4129f1fab81212ef1e9b128c61514559a46fae4 Mon Sep 17 00:00:00 2001 From: Malasaur Date: Wed, 3 Sep 2025 14:32:26 +0200 Subject: [PATCH] Added console --- console.py | 37 ++++++++++++++++++ requirements.txt | 1 + test2.py | 100 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 138 insertions(+) create mode 100644 console.py create mode 100644 test2.py diff --git a/console.py b/console.py new file mode 100644 index 0000000..a5c876a --- /dev/null +++ b/console.py @@ -0,0 +1,37 @@ +from os import environ +from threading import Lock, Thread +from sseclient import SSEClient +from dotenv import load_dotenv +from requests import post + +load_dotenv() +MCSMGR_ADDRESS = environ.get("MCSMGR_ADDRESS", "http://localhost:8000") +MCSMGR_PASSWORD = environ.get("MCSMGR_PASSWORD", "SuperSecretPassword") +MINECRAFT_SERVER_COMMAND = environ.get( + "MINECRAFT_SERVER_COMMAND", "java -jar fabric.jar nogui") +MINECRAFT_SERVER_ADDRESS = environ.get("MINECRAFT_SERVER_ADDRESS", "localhost") +MINECRAFT_SERVER_RCON_PORT = int( + environ.get("MINECRAFT_SERVER_RCON_PORT", "25575")) +MINECRAFT_SERVER_RCON_PASSWORD = environ.get( + "MINECRAFT_SERVER_RCON_PASSWORD", "SuperSecretPassword") + + +post(MCSMGR_ADDRESS+"/start") + + +def logger(): + for msg in SSEClient(MCSMGR_ADDRESS+"/logs", json={"password": MCSMGR_PASSWORD}): + print(msg.data) + + +t = Thread(target=logger, daemon=True) +t.start() + +try: + while True: + cmd = input() + response = post(MCSMGR_ADDRESS+"/command", json={ + "password": MCSMGR_PASSWORD, "cmd": cmd}) + print(eval(response.text).rstrip("\n")) +except (KeyboardInterrupt, EOFError): + t.join() diff --git a/requirements.txt b/requirements.txt index 8419296..4e59aaa 100644 --- a/requirements.txt +++ b/requirements.txt @@ -20,6 +20,7 @@ requests==2.32.5 setuptools==80.9.0 six==1.17.0 sniffio==1.3.1 +sseclient==0.0.27 starlette==0.47.3 typing-inspection==0.4.1 typing_extensions==4.15.0 diff --git a/test2.py b/test2.py new file mode 100644 index 0000000..4ed8590 --- /dev/null +++ b/test2.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +import curses +import curses.textpad +import locale +import time + +locale.setlocale(locale.LC_ALL, '') + +logs = [] + + +def main(stdscr): + curses.curs_set(1) + stdscr.nodelay(False) + stdscr.keypad(True) + + prompt = "> " + + def resize_windows(): + nonlocal main_win, input_win, maxy, maxx, input_box + stdscr.clear() + maxy, maxx = stdscr.getmaxyx() + + main_win = stdscr.derwin(maxy - 1, maxx, 0, 0) + main_win.keypad(True) + main_win.nodelay(True) + main_win.scrollok(True) + + input_win = stdscr.derwin(1, maxx, maxy - 1, 0) + input_win.keypad(True) + + input_box = input_win.derwin(1, maxx - len(prompt), 0, len(prompt)) + draw_screen() + + def draw_screen(): + if main_win is None or input_win is None: + return + + main_win.erase() + + height, width = main_win.getmaxyx() + start = max(0, len(logs) - height) + visible = logs[start:] + for i, line in enumerate(visible): + main_win.addnstr(i, 0, line, width - 1) + main_win.noutrefresh() + + input_win.erase() + input_win.addstr(0, 0, prompt) + + if maxy > 1: + stdscr.hline(maxy - 2, 0, curses.ACS_HLINE, maxx) + input_win.noutrefresh() + curses.doupdate() + + maxy = maxx = 0 + main_win = input_win = input_box = None + resize_windows() + if input_box is None: + return + + textbox = curses.textpad.Textbox(input_box, insert_mode=True) + + while True: + draw_screen() + + def validator(ch): + nonlocal logs + if ch in (curses.KEY_RESIZE,): + + resize_windows() + return 0 + if ch in (10, 13): + return 7 + return ch + + input_box.erase() + input_box.refresh() + curses.curs_set(1) + s = textbox.edit(validator).strip() + curses.curs_set(0) + + if s: + + if s.strip().lower() in ("/quit", "/q", "quit"): + break + + timestamp = time.strftime("%H:%M:%S") + logs.append(f"[{timestamp}] {s}") + else: + + pass + + if curses.is_term_resized(maxy, maxx): + curses.resizeterm(*stdscr.getmaxyx()) + resize_windows() + + +if __name__ == "__main__": + curses.wrapper(main)