diff --git a/api.py b/api.py index c695ff6..65e696d 100644 --- a/api.py +++ b/api.py @@ -1,13 +1,15 @@ import requests import json +from execptions import InvalidLogin, InvalidURL, InvalidMethod, InvalidServerState class API: - def __init__(self, url: str, username: str, password: str, port: int = 5000): + def __init__(self, url: str, username: str, password: str): + if url[-1] == "/": + url = url[:-1] self.url = url self.username = username self.password = password - self.port = port self.token = None self._auth() @@ -15,9 +17,11 @@ class API: try: resp = requests.post(self.url+"/auth", json={"username": self.username, "password": self.password}) except (json.JSONDecodeError, KeyError): - raise Exception("InvalidLogin") + raise InvalidLogin except requests.exceptions.ConnectionError: - raise Exception("Connection Error") + raise ConnectionError + except requests.exceptions.MissingSchema: + raise InvalidURL else: self.token = {"Authorization": f"jwt {resp.json()['access_token']}"} @@ -29,12 +33,14 @@ class API: resp = requests.get(self.url+args, headers=self.token, json=body) elif method == "put": resp = requests.put(self.url + args, headers=self.token, json=body) + elif method == "post": + resp = requests.post(self.url+args, headers=self.token, json=body) else: - raise Exception("Invalid method") + raise InvalidMethod if resp.status_code == 401: self._auth() - self._request(args, body, method) + return self._request(args, body, method) else: return resp @@ -47,7 +53,7 @@ class API: msg = "Server did not respond" else: msg = text - raise Exception(msg) + raise InvalidServerState(msg) def status(self): resp = self._request("/") @@ -86,7 +92,7 @@ class API: return True def cmd(self, cmd): - resp = self._request("/cmd/"+cmd) + resp = self._request("/cmd", {"command": cmd}, "post") if resp.status_code == 400: self.code_400(resp.text) else: diff --git a/execptions.py b/execptions.py new file mode 100644 index 0000000..569d3b0 --- /dev/null +++ b/execptions.py @@ -0,0 +1,14 @@ +class InvalidLogin(Exception): + pass + + +class InvalidURL(Exception): + pass + + +class InvalidMethod(Exception): + pass + + +class InvalidServerState(Exception): + pass \ No newline at end of file diff --git a/gui.py b/gui.py index e69de29..53c3853 100644 --- a/gui.py +++ b/gui.py @@ -0,0 +1,195 @@ +from threading import Thread +from tkinter import Tk, StringVar, Label, Frame, Entry, Button, Scrollbar, Text, END, LabelFrame, IntVar +from tkinter.messagebox import showerror +from api import API +from execptions import InvalidLogin, InvalidURL, InvalidServerState +from time import sleep + +api = None +destroy = False + + +def login_close(): + if not api: + login_w.destroy() + exit() + + +def main_close(): + global destroy + destroy = True + main_w.destroy() + + +def login(): + if url.get() and username.get() and password.get(): + try: + global api + api = API(url.get(), username.get(), password.get()) + except InvalidLogin: + showerror("Login error", "Login invalid !") + except InvalidURL: + showerror("URL error", "Invalid URL !") + except ConnectionError: + showerror("Connexion error", "Connexion error !") + else: + login_w.destroy() + + +def start(): + try: + api.start() + except InvalidServerState: + showerror("Invalid state", "The server is online !") + + +def stop(): + try: + api.stop() + except InvalidServerState: + showerror("Invalid state", 'The server is offline !') + + +def restart(): + try: + api.stop() + while api.status(): + sleep(1) + sleep(2) + api.start() + except InvalidServerState: + showerror("Invalid state", "The server is offline !") + + +def kill(): + try: + api.kill() + except InvalidServerState: + showerror("Invalid state", "The server is online !") + + +def thread_loop(): + while not destroy: + try: + state = api.status() + msg = api.logs() + except InvalidServerState: + online.set("Offline") + toggle_b.configure(text="Start", command=start) + reboot_b.configure(state="disable") + kill_b.configure(state="disable") + players.set(0) + latency.set(0) + field.configure(state="disable") + send.configure(state="disable") + logs_text.delete("1.0", END) + sleep(4) + else: + if state: + toggle_b.configure(text="Stop", command=stop) + reboot_b.configure(state="normal") + kill_b.configure(state="normal") + online.set("Online") + players.set(state[0]) + latency.set(state[1]) + field.configure(state="normal") + send.configure(state="normal") + else: + online.set("Idle...") + update_logs(msg) + sleep(1) + + +def update_logs(msg: str): + # msg = msg.split("\n") + # content = logs.get("1.0", END).split("\n") + # msg = "\n".join(msg[len(content):]) + if not destroy: + logs_text.configure(state="normal") + logs_text.replace("1.0", END, msg) + logs_text.configure(state="disable") + logs_text.yview(END) + + +def command_send(event=None): + try: + api.cmd(cmd.get()) + except InvalidServerState: + showerror("Server error", "Command not send, can't connect to the server !") + cmd.set("") + + +login_w = Tk() +login_w.title("Minecraft Server Login") +login_w.resizable(0, 0) +login_w.protocol("WM_DELETE_WINDOW", login_close) +username = StringVar() +password = StringVar() +url = StringVar() +username.set("admin") +password.set("admin") +url.set("http://127.0.0.1:5000") +Label(login_w, text="Url:").pack() +login_hp = Frame(login_w) +login_hp.pack() +Entry(login_hp, textvariable=url, width=28).grid(row=0, column=0) +Label(login_w, text="Username & password:").pack() +login_up = Frame(login_w) +login_up.pack() +Entry(login_up, textvariable=username, width=14).grid(row=0, column=0) +Entry(login_up, textvariable=password, show="*", width=14).grid(row=0, column=1) +Button(login_w, text="Submit", command=login).pack() +login_w.mainloop() + + +main_w = Tk() +main_w.title("Minecraft Server") +main_w.resizable(0, 0) +main_w.protocol("WM_DELETE_WINDOW", main_close) + +sid_bar = Frame(main_w) +sid_bar.grid(row=0, column=0) +status = LabelFrame(sid_bar, text="Status") +status.pack() +Label(status, text="State:").grid(row=0, column=0) +online = StringVar() +online.set("N/A") +Label(status, textvariable=online).grid(row=0, column=1) +Label(status, text="Players:").grid(row=1, column=0) +players = IntVar() +players.set(0) +Label(status, textvariable=players).grid(row=1, column=1) +Label(status, text="Latency:").grid(row=2, column=0) +latency = IntVar() +latency.set(0) +Label(status, textvariable=latency).grid(row=2, column=1) +actions = LabelFrame(sid_bar, text="Actions") +actions.pack() +toggle_b = Button(actions, text="Start", command=start) +toggle_b.pack() +reboot_b = Button(actions, text="Reboot", command=restart) +reboot_b.pack() +kill_b = Button(actions, text="Kill", command=kill) +kill_b.pack() + +console = LabelFrame(main_w, text="Console") +console.grid(row=0, column=1) +logs = Frame(console) +logs.pack() +scrollbar = Scrollbar(logs) +scrollbar.pack(side="right", fill="y") +logs_text = Text(logs, height=30, width=100, yscrollcommand=scrollbar.set, state="disable") +logs_text.pack(side="left", fill="both") +command = Frame(console) +command.pack() +cmd = StringVar() +field = Entry(command, textvariable=cmd, width=80) +field.bind("", command_send) +field.grid(row=0, column=0) +send = Button(command, text="Send", command=command_send) +send.grid(row=0, column=1) + +thread = Thread(target=thread_loop) +thread.start() +main_w.mainloop() +