From a67f53a4c96243fe1055c9b86b371445538d2f93 Mon Sep 17 00:00:00 2001 From: Andrew Date: Thu, 28 Dec 2023 18:34:35 -0500 Subject: [PATCH 01/84] Fix bukkit and downstream fork MOTD crash --- app/classes/minecraft/mc_ping.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/classes/minecraft/mc_ping.py b/app/classes/minecraft/mc_ping.py index c5cb9916..84b69505 100644 --- a/app/classes/minecraft/mc_ping.py +++ b/app/classes/minecraft/mc_ping.py @@ -34,8 +34,13 @@ class Server: lines = [] description = self.description + if "text" in description.keys(): + lines.append(description["text"]) if "extra" in description.keys(): for e in description["extra"]: + if not isinstance(e, dict): + lines.append(e) + continue # Conversion format code needed only for Java Version lines.append(get_code_format("reset")) if "bold" in e.keys(): From 60ac3bf630fa9efe252e2a9d5390637089b7caf5 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 29 Dec 2023 12:11:29 -0500 Subject: [PATCH 02/84] Check type in extra so we don't iterate thru str --- app/classes/minecraft/mc_ping.py | 41 +++++++++++++++----------------- 1 file changed, 19 insertions(+), 22 deletions(-) diff --git a/app/classes/minecraft/mc_ping.py b/app/classes/minecraft/mc_ping.py index 84b69505..72a91351 100644 --- a/app/classes/minecraft/mc_ping.py +++ b/app/classes/minecraft/mc_ping.py @@ -12,6 +12,7 @@ from app.classes.minecraft.bedrock_ping import BedrockPing from app.classes.shared.console import Console logger = logging.getLogger(__name__) +MOTD_CODES = ["bold", "italic", "underlined", "strikethrough"] class Server: @@ -37,28 +38,24 @@ class Server: if "text" in description.keys(): lines.append(description["text"]) if "extra" in description.keys(): - for e in description["extra"]: - if not isinstance(e, dict): - lines.append(e) - continue - # Conversion format code needed only for Java Version - lines.append(get_code_format("reset")) - if "bold" in e.keys(): - lines.append(get_code_format("bold")) - if "italic" in e.keys(): - lines.append(get_code_format("italic")) - if "underlined" in e.keys(): - lines.append(get_code_format("underlined")) - if "strikethrough" in e.keys(): - lines.append(get_code_format("strikethrough")) - if "color" in e.keys(): - lines.append(get_code_format(e["color"])) - # Then append the text - if "text" in e.keys(): - if e["text"] == "\n": - lines.append("§§") - else: - lines.append(e["text"]) + if isinstance(description["extra"], list): + for e in description["extra"]: + if not isinstance(e, dict): + lines.append(e) + continue + # Conversion format code needed only for Java Version + lines.append(get_code_format("reset")) + for item in MOTD_CODES: + if e.get(item, False): + lines.append(get_code_format(item)) + if "color" in e.keys(): + lines.append(get_code_format(e["color"])) + # Then append the text + if "text" in e.keys(): + if e["text"] == "\n": + lines.append("§§") + else: + lines.append(e["text"]) total_text = " ".join(lines) self.description = total_text From dc09f478715a58a5fda01652ccc29f320ee737c4 Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Wed, 3 Jan 2024 21:10:33 +0100 Subject: [PATCH 03/84] Fixing issues for forge installation for versions >= 1.20 --- app/classes/shared/server.py | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 8448f656..035824c5 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -725,8 +725,9 @@ class ServerInstance: server_obj.execution_command = execution_command Console.debug("SUCCESS! Forge install completed") - else: - # NEW VERSION >= 1.17 + elif version_major <= 1 and version_minor < 20: + # NEW VERSION >= 1.17 and <= 1.20 + # (no jar file in server dir, only run.bat and run.sh) run_file_path = "" if self.helper.is_os_windows(): @@ -771,6 +772,37 @@ class ServerInstance: ) server_obj.execution_command = execution_command Console.debug("SUCCESS! Forge install completed") + else: + # NEW VERSION >= 1.20 + # (executable jar is back in server dir) + + # Retrieving the executable jar filename + file_path = glob.glob( + f"{server_obj.path}/forge-{version[0][0]}*.jar" + )[0] + file_name = re.findall( + r"(forge-[\-0-9.]+-shim.jar)", + file_path, + )[0] + + # Let's set the proper server executable + server_obj.executable = os.path.join(file_name) + + # Get memory values + memory_values = re.findall( + r"-Xms([A-Z0-9\.]+) -Xmx([A-Z0-9\.]+)", + server_obj.execution_command, + ) + + # Now lets set up the new run command. + # This is based off the run.sh/bat that + # Forge uses in 1.17 and < + execution_command = ( + f"java -Xms{memory_values[0][0]} -Xmx{memory_values[0][1]}" + f' -jar "{file_name}" nogui' + ) + server_obj.execution_command = execution_command + Console.debug("SUCCESS! Forge install completed") except: logger.debug("Could not find run file.") # TODO Use regex to get version and rebuild simple execution From 9d319b74604cfae1b150a5e5a50182d96ce54812 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Thu, 11 Jan 2024 16:11:08 -0500 Subject: [PATCH 04/84] Fix unicode chars in terminal w/ texitiowrapper --- app/classes/shared/server.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 8448f656..48816d1c 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -1,5 +1,6 @@ from contextlib import redirect_stderr import os +import io import re import shutil import time @@ -115,14 +116,17 @@ class ServerOutBuf: ServerOutBuf.lines[self.server_id].pop(0) def check(self): + text_wrapper = io.TextIOWrapper( + self.proc.stdout, encoding="UTF-8", errors="ignore", newline="" + ) while True: if self.proc.poll() is None: - char = self.proc.stdout.read(1).decode("utf-8", "ignore") + char = text_wrapper.read(1) # modified # TODO: we may want to benchmark reading in blocks and userspace # processing it later, reads are kind of expensive as a syscall self.process_byte(char) else: - flush = self.proc.stdout.read().decode("utf-8", "ignore") + flush = text_wrapper.read() # modified for char in flush: self.process_byte(char) break From e274b0c67767bb4ec65a10e4cb17ae7fc7586f41 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Thu, 11 Jan 2024 19:20:50 -0500 Subject: [PATCH 05/84] Implement paper builds using mineacademy API Big shoutout to zed for fnding this --- app/classes/minecraft/serverjars.py | 30 ++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/app/classes/minecraft/serverjars.py b/app/classes/minecraft/serverjars.py index 447cf80b..55e98a80 100644 --- a/app/classes/minecraft/serverjars.py +++ b/app/classes/minecraft/serverjars.py @@ -11,12 +11,14 @@ from app.classes.models.server_permissions import PermissionsServers from app.classes.shared.websocket_manager import WebSocketManager logger = logging.getLogger(__name__) +MINEACADEMYJARS = ["paper", "folia"] class ServerJars: def __init__(self, helper): self.helper = helper self.base_url = "https://serverjars.com" + self.academy = "https://mineacademy.org" def _get_api_result(self, call_url: str): full_url = f"{self.base_url}{call_url}" @@ -38,6 +40,23 @@ class ServerJars: return api_response + def get_paper_versions(self, project): + try: + response = requests.get( + f"https://api.papermc.io/v2/projects/{project}/", timeout=2 + ) + response.raise_for_status() + api_data = json.loads(response.content) + except Exception as e: + logger.error( + f"Unable to load https://api.papermc.io/v2/projects/{project}/" + f"api due to error: {e}" + ) + return {} + versions = api_data.get("versions", []) + versions.reverse() + return versions + def _read_cache(self): cache_file = self.helper.serverjar_cache cache = {} @@ -95,6 +114,8 @@ class ServerJars: for j in data["types"].get(s): versions = self._get_jar_details(j, s) data["types"][s].update({j: versions}) + for item in MINEACADEMYJARS: + data["types"]["servers"][item] = self.get_paper_versions(item) # save our cache try: with open(cache_file, "w", encoding="utf-8") as f: @@ -133,6 +154,8 @@ class ServerJars: for j in data["types"].get(s): versions = self._get_jar_details(j, s) data["types"][s].update({j: versions}) + for item in MINEACADEMYJARS: + data["types"]["servers"][item] = self.get_paper_versions() # save our cache try: with open(cache_file, "w", encoding="utf-8") as f: @@ -171,7 +194,12 @@ class ServerJars: def a_download_jar(self, jar, server, version, path, server_id): # delaying download for server register to finish time.sleep(3) - fetch_url = f"{self.base_url}/api/fetchJar/{jar}/{server}/{version}" + if server not in MINEACADEMYJARS: + fetch_url = f"{self.base_url}/api/fetchJar/{jar}/{server}/{version}" + else: + fetch_url = ( + f"https://mineacademy.org/api/{server}/{str(version).replace('.', '_')}" + ) server_users = PermissionsServers.get_server_user_list(server_id) # We need to make sure the server is registered before From cd3b8d4d9cdc8ad11173f7b163ddd9e4ee86c350 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Thu, 11 Jan 2024 19:35:08 -0500 Subject: [PATCH 06/84] Fix update urls --- app/classes/minecraft/serverjars.py | 4 ++++ app/classes/shared/main_controller.py | 15 +++++++++++---- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/app/classes/minecraft/serverjars.py b/app/classes/minecraft/serverjars.py index 55e98a80..5c6d6d91 100644 --- a/app/classes/minecraft/serverjars.py +++ b/app/classes/minecraft/serverjars.py @@ -20,6 +20,10 @@ class ServerJars: self.base_url = "https://serverjars.com" self.academy = "https://mineacademy.org" + @staticmethod + def get_mineacademy_jars(): + return MINEACADEMYJARS + def _get_api_result(self, call_url: str): full_url = f"{self.base_url}{call_url}" diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py index ae58d988..60f3c5df 100644 --- a/app/classes/shared/main_controller.py +++ b/app/classes/shared/main_controller.py @@ -538,10 +538,17 @@ class Controller: # modded update urls from server jars will only update the installer if create_data["category"] != "modded": server_obj = self.servers.get_server_obj(new_server_id) - url = ( - f"https://serverjars.com/api/fetchJar/{create_data['category']}" - f"/{create_data['type']}/{create_data['version']}" - ) + if create_data["type"] not in ServerJars.get_mineacademy_jars(): + url = ( + "https://serverjars.com/api/fetchJar/" + f"{create_data['category']}" + f"/{create_data['type']}/{create_data['version']}" + ) + else: + url = ( + "https://mineacademy.org/api/" + f"{create_data['type']}/{create_data['version']}" + ) server_obj.executable_update_url = url self.servers.update_server(server_obj) self.server_jars.download_jar( From 5f2236563baf2af1c76ae4807583f14eb395f5d3 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Thu, 11 Jan 2024 19:53:22 -0500 Subject: [PATCH 07/84] Fix bug where invalid server Id leads to stack --- app/classes/controllers/servers_controller.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/classes/controllers/servers_controller.py b/app/classes/controllers/servers_controller.py index 88923194..86e17802 100644 --- a/app/classes/controllers/servers_controller.py +++ b/app/classes/controllers/servers_controller.py @@ -462,7 +462,10 @@ class ServersController(metaclass=Singleton): @staticmethod def server_id_exists(server_id): - srv = ServersController().get_server_instance_by_id(server_id) + try: + srv = ServersController().get_server_instance_by_id(server_id) + except ValueError: + return False return srv.stats_helper.server_id_exists() @staticmethod From 96d5ce58d2e2d675a237c9adfc0dd0620c2c13f9 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 12 Jan 2024 11:23:35 -0500 Subject: [PATCH 08/84] Get jars direct frrom paper --- app/classes/minecraft/serverjars.py | 40 +++++++++++++++++++++------ app/classes/shared/main_controller.py | 2 +- 2 files changed, 32 insertions(+), 10 deletions(-) diff --git a/app/classes/minecraft/serverjars.py b/app/classes/minecraft/serverjars.py index 5c6d6d91..cadcb376 100644 --- a/app/classes/minecraft/serverjars.py +++ b/app/classes/minecraft/serverjars.py @@ -11,18 +11,18 @@ from app.classes.models.server_permissions import PermissionsServers from app.classes.shared.websocket_manager import WebSocketManager logger = logging.getLogger(__name__) -MINEACADEMYJARS = ["paper", "folia"] +PAPERJARS = ["paper", "folia"] class ServerJars: def __init__(self, helper): self.helper = helper self.base_url = "https://serverjars.com" - self.academy = "https://mineacademy.org" + self.paper_base = "https://api.papermc.io" @staticmethod - def get_mineacademy_jars(): - return MINEACADEMYJARS + def get_paper_jars(): + return PAPERJARS def _get_api_result(self, call_url: str): full_url = f"{self.base_url}{call_url}" @@ -47,7 +47,7 @@ class ServerJars: def get_paper_versions(self, project): try: response = requests.get( - f"https://api.papermc.io/v2/projects/{project}/", timeout=2 + f"{self.paper_base}/v2/projects/{project}/", timeout=2 ) response.raise_for_status() api_data = json.loads(response.content) @@ -61,6 +61,23 @@ class ServerJars: versions.reverse() return versions + def get_paper_build(self, project, version): + try: + response = requests.get( + f"{self.paper_base}/v2/projects/{project}/versions/{version}/builds/", + timeout=2, + ) + response.raise_for_status() + api_data = json.loads(response.content) + except Exception as e: + logger.error( + f"Unable to load https://api.papermc.io/v2/projects/{project}/" + f"api due to error: {e}" + ) + return {} + build = api_data.get("builds", [])[-1] + return build + def _read_cache(self): cache_file = self.helper.serverjar_cache cache = {} @@ -118,7 +135,7 @@ class ServerJars: for j in data["types"].get(s): versions = self._get_jar_details(j, s) data["types"][s].update({j: versions}) - for item in MINEACADEMYJARS: + for item in PAPERJARS: data["types"]["servers"][item] = self.get_paper_versions(item) # save our cache try: @@ -158,7 +175,7 @@ class ServerJars: for j in data["types"].get(s): versions = self._get_jar_details(j, s) data["types"][s].update({j: versions}) - for item in MINEACADEMYJARS: + for item in PAPERJARS: data["types"]["servers"][item] = self.get_paper_versions() # save our cache try: @@ -198,11 +215,16 @@ class ServerJars: def a_download_jar(self, jar, server, version, path, server_id): # delaying download for server register to finish time.sleep(3) - if server not in MINEACADEMYJARS: + if server not in PAPERJARS: fetch_url = f"{self.base_url}/api/fetchJar/{jar}/{server}/{version}" else: + build = self.get_paper_build(server, version).get("build", None) + if not build: + return fetch_url = ( - f"https://mineacademy.org/api/{server}/{str(version).replace('.', '_')}" + f"{self.paper_base}/v2/projects" + f"/{server}/versions/{version}/builds/{build}/downloads/" + f"{server}-{version}-{build}.jar" ) server_users = PermissionsServers.get_server_user_list(server_id) diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py index 60f3c5df..ffc355ea 100644 --- a/app/classes/shared/main_controller.py +++ b/app/classes/shared/main_controller.py @@ -538,7 +538,7 @@ class Controller: # modded update urls from server jars will only update the installer if create_data["category"] != "modded": server_obj = self.servers.get_server_obj(new_server_id) - if create_data["type"] not in ServerJars.get_mineacademy_jars(): + if create_data["type"] not in ServerJars.get_paper_jars(): url = ( "https://serverjars.com/api/fetchJar/" f"{create_data['category']}" From e3dee7dcd6ac144f14041763224dbda2deb9bc13 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 12 Jan 2024 13:43:04 -0500 Subject: [PATCH 09/84] Fix indent on checkbox on server config --- app/frontend/templates/panel/server_config.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/frontend/templates/panel/server_config.html b/app/frontend/templates/panel/server_config.html index 46f7b4dc..137dc847 100644 --- a/app/frontend/templates/panel/server_config.html +++ b/app/frontend/templates/panel/server_config.html @@ -195,7 +195,7 @@ {% else %} -    + {% end %} {% end %} From 78b2feab01c8dd997e9c6bd9558a55964b9740f7 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 12 Jan 2024 14:46:25 -0500 Subject: [PATCH 10/84] Remove update url for paper builds --- app/classes/shared/main_controller.py | 21 +++++++++------------ 1 file changed, 9 insertions(+), 12 deletions(-) diff --git a/app/classes/shared/main_controller.py b/app/classes/shared/main_controller.py index ffc355ea..216c13e9 100644 --- a/app/classes/shared/main_controller.py +++ b/app/classes/shared/main_controller.py @@ -536,19 +536,16 @@ class Controller: if data["create_type"] == "minecraft_java": if root_create_data["create_type"] == "download_jar": # modded update urls from server jars will only update the installer - if create_data["category"] != "modded": + if ( + create_data["category"] != "modded" + and create_data["type"] not in ServerJars.get_paper_jars() + ): server_obj = self.servers.get_server_obj(new_server_id) - if create_data["type"] not in ServerJars.get_paper_jars(): - url = ( - "https://serverjars.com/api/fetchJar/" - f"{create_data['category']}" - f"/{create_data['type']}/{create_data['version']}" - ) - else: - url = ( - "https://mineacademy.org/api/" - f"{create_data['type']}/{create_data['version']}" - ) + url = ( + "https://serverjars.com/api/fetchJar/" + f"{create_data['category']}" + f"/{create_data['type']}/{create_data['version']}" + ) server_obj.executable_update_url = url self.servers.update_server(server_obj) self.server_jars.download_jar( From 90806b613cfeb2c3dd3deea75a7cc8c5527fad48 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 12 Jan 2024 18:33:21 -0500 Subject: [PATCH 11/84] Fix log file output on page --- app/frontend/templates/panel/server_logs.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/frontend/templates/panel/server_logs.html b/app/frontend/templates/panel/server_logs.html index 9a4033a1..32f3cb66 100644 --- a/app/frontend/templates/panel/server_logs.html +++ b/app/frontend/templates/panel/server_logs.html @@ -192,7 +192,7 @@ const token = getCookie("_xsrf") let colors = true; if (!$("#stop_scroll").is(':checked')) { - let res = await fetch(`/api/v2/servers/${serverId}/logs?colors=${colors}`, { + let res = await fetch(`/api/v2/servers/${serverId}/logs?colors=${colors}&file=true`, { method: 'GET', headers: { 'X-XSRFToken': token From 589a11f43ccb852d17122b2a8c194aecfb30ab6b Mon Sep 17 00:00:00 2001 From: Andrew Date: Sat, 13 Jan 2024 16:43:16 -0500 Subject: [PATCH 12/84] Allow omission of player stats from total --- app/classes/models/servers.py | 1 + app/classes/shared/server.py | 1 + .../web/routes/api/servers/server/index.py | 2 ++ app/frontend/templates/panel/dashboard.html | 16 ++++++++++++---- app/frontend/templates/panel/server_config.html | 12 ++++++++++++ app/migrations/20231229_player_count.py | 16 ++++++++++++++++ app/translations/en_EN.json | 5 +++-- 7 files changed, 47 insertions(+), 6 deletions(-) create mode 100644 app/migrations/20231229_player_count.py diff --git a/app/classes/models/servers.py b/app/classes/models/servers.py index a83fd0a2..00bc5002 100644 --- a/app/classes/models/servers.py +++ b/app/classes/models/servers.py @@ -42,6 +42,7 @@ class Servers(BaseModel): created_by = IntegerField(default=-100) shutdown_timeout = IntegerField(default=60) ignored_exits = CharField(default="0") + count_players = BooleanField(default=True) class Meta: table_name = "servers" diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 8448f656..15544a26 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -1560,6 +1560,7 @@ class ServerInstance: "version": raw_ping_result.get("version"), "icon": raw_ping_result.get("icon"), "crashed": self.is_crashed, + "count_players": self.server_object.count_players, } ) diff --git a/app/classes/web/routes/api/servers/server/index.py b/app/classes/web/routes/api/servers/server/index.py index afe02a0b..06db3158 100644 --- a/app/classes/web/routes/api/servers/server/index.py +++ b/app/classes/web/routes/api/servers/server/index.py @@ -29,6 +29,7 @@ server_patch_schema = { "logs_delete_after": {"type": "integer", "minimum": 0}, "ignored_exits": {"type": "string"}, "show_status": {"type": "boolean"}, + "count_players": {"type": "boolean"}, }, "additionalProperties": False, "minProperties": 1, @@ -46,6 +47,7 @@ basic_server_patch_schema = { "shutdown_timeout": {"type": "integer"}, "logs_delete_after": {"type": "integer", "minimum": 0}, "ignored_exits": {"type": "string"}, + "count_players": {"type": "boolean"}, }, "additionalProperties": False, "minProperties": 1, diff --git a/app/frontend/templates/panel/dashboard.html b/app/frontend/templates/panel/dashboard.html index 88c9a821..eb4a51a9 100644 --- a/app/frontend/templates/panel/dashboard.html +++ b/app/frontend/templates/panel/dashboard.html @@ -315,7 +315,7 @@

- + {% end %} @@ -554,6 +554,9 @@ display: none; /* for Chrome, Safari, and Opera */ } + .gray { + color: gray !important; + } @@ -724,15 +727,20 @@ server_players.setAttribute('data-players', server.online); server_players.setAttribute('data-max', server.max); + server_players.setAttribute('data-count', server.count_players) let servers = Array.from(document.getElementsByClassName("server-player-totals")); let all_total_players = 0; let all_total_max_players = 0; servers.forEach(server => { try { - all_total_players += parseInt(server.getAttribute('data-players')); - all_total_max_players += parseInt(server.getAttribute('data-max')); - } catch { + console.log(`#server_desc_${server.getAttribute("data-serverId")}`) + $(`#server_desc_${server.getAttribute("data-serverId")}`).toggleClass("gray", server.getAttribute('data-count') === 'false') + if (server.getAttribute('data-count') === 'true'){ + all_total_players += parseInt(server.getAttribute('data-players')); + all_total_max_players += parseInt(server.getAttribute('data-max')); + } + } catch { console.log("Player totals are not of type int"); } }) diff --git a/app/frontend/templates/panel/server_config.html b/app/frontend/templates/panel/server_config.html index 46f7b4dc..6b29ea7c 100644 --- a/app/frontend/templates/panel/server_config.html +++ b/app/frontend/templates/panel/server_config.html @@ -188,6 +188,17 @@ {% end %} +
+
+ {% if data['server_stats']['server_id']['count_players'] %} + + + {% else %} + + + {% end %} +
+
{% if data['super_user'] %} @@ -559,6 +570,7 @@ formDataObject.show_status = $("#show_status").prop('checked'); formDataObject.crash_detection = $("#crash_detection").prop('checked'); formDataObject.auto_start = $("#auto_start").prop('checked'); + formDataObject.count_players = $("#count_players").prop('checked'); console.log(formDataObject); // Format the plain form data as JSON let formDataJsonString = JSON.stringify(formDataObject, replacer); diff --git a/app/migrations/20231229_player_count.py b/app/migrations/20231229_player_count.py new file mode 100644 index 00000000..0f7f1876 --- /dev/null +++ b/app/migrations/20231229_player_count.py @@ -0,0 +1,16 @@ +# Generated by database migrator +import peewee + + +def migrate(migrator, database, **kwargs): + migrator.add_columns("servers", count_players=peewee.BooleanField(default=True)) + """ + Write your migrations here. + """ + + +def rollback(migrator, database, **kwargs): + migrator.drop_columns("servers", ["count_players"]) + """ + Write your rollback migrations here. + """ diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 4db8be71..a717c929 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -377,7 +377,8 @@ "timeoutExplain2": "command before it forces the process down.", "update": "Update Executable", "yesDelete": "Yes, delete", - "yesDeleteFiles": "Yes, delete files" + "yesDeleteFiles": "Yes, delete files", + "countPlayers": "Include server in total player count" }, "serverConfigHelp": { "desc": "Here is where you can change the configuration of your server", @@ -665,4 +666,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} +} \ No newline at end of file From 1b047b1733ab9f92e6e46e82ef798ee99af443ce Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sat, 13 Jan 2024 18:27:25 -0500 Subject: [PATCH 13/84] Remove scroll bars from player management --- app/frontend/templates/panel/parts/server_players.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/frontend/templates/panel/parts/server_players.html b/app/frontend/templates/panel/parts/server_players.html index ca81f39e..9f8d1e62 100644 --- a/app/frontend/templates/panel/parts/server_players.html +++ b/app/frontend/templates/panel/parts/server_players.html @@ -11,13 +11,13 @@ {% for player in data['cached_players'] %} - + {{ player['name'] }} {% if player['status'] == 'Online' %} - {{ player['status'] }} + {{ player['status'] }} {% elif player['status'] == 'Offline' %} -  {{ player['status'] }} Last connection :
{{ player['last_seen'] }}
+  {{ player['status'] }} Last connection :
{{ player['last_seen'] }}
{% end %} {% if data['server_stats']['running'] %} From c43749cc7cb5c8555fd33274192c259a375d58d1 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 17:53:21 +0000 Subject: [PATCH 14/84] Update changelog !686 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 71b8b4b6..a2c3c9e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,7 @@ ### New features TBD ### Bug fixes -TBD +- Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) ### Tweaks TBD ### Lang From b76636ed994accfba69b0e4fffd8650417b090ee Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 18:04:59 +0000 Subject: [PATCH 15/84] Update changelog !687 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a2c3c9e5..6e94d0db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ TBD ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) ### Tweaks -TBD +- Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) ### Lang TBD

From 09c2917e27a644e07c01add8d527df81c365596e Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 18:26:17 +0000 Subject: [PATCH 16/84] Update changelog !688 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6e94d0db..c2432de2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Changelog ## --- [4.2.3] - 2023/TBD ### New features -TBD +- Use Papermc Group's API for `paper` & `folia` builds in server builder ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/688)) ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) ### Tweaks From 7d7ae02bebd5ea5de76e2aac8a7b05b503537c7e Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 13:50:05 -0500 Subject: [PATCH 17/84] Add parameter to version call --- app/classes/minecraft/serverjars.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/minecraft/serverjars.py b/app/classes/minecraft/serverjars.py index cadcb376..29675e8d 100644 --- a/app/classes/minecraft/serverjars.py +++ b/app/classes/minecraft/serverjars.py @@ -176,7 +176,7 @@ class ServerJars: versions = self._get_jar_details(j, s) data["types"][s].update({j: versions}) for item in PAPERJARS: - data["types"]["servers"][item] = self.get_paper_versions() + data["types"]["servers"][item] = self.get_paper_versions(item) # save our cache try: with open(cache_file, "w", encoding="utf-8") as f: From 0b520aae80c5d059044379853154388a9376709d Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 13:53:50 -0500 Subject: [PATCH 18/84] Fix misc sonarcube finding --- app/classes/shared/server.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 035824c5..f413b0f2 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -43,6 +43,7 @@ with redirect_stderr(NullWriter()): from psutil import NoSuchProcess logger = logging.getLogger(__name__) +SUCCESSMSG = "SUCCESS! Forge install completed" def callback(called_func): @@ -723,7 +724,7 @@ class ServerInstance: f' -jar "{file_name}" nogui' ) server_obj.execution_command = execution_command - Console.debug("SUCCESS! Forge install completed") + Console.debug(SUCCESSMSG) elif version_major <= 1 and version_minor < 20: # NEW VERSION >= 1.17 and <= 1.20 @@ -771,7 +772,7 @@ class ServerInstance: f" {server_command[4]}" ) server_obj.execution_command = execution_command - Console.debug("SUCCESS! Forge install completed") + Console.debug(SUCCESSMSG) else: # NEW VERSION >= 1.20 # (executable jar is back in server dir) @@ -802,7 +803,7 @@ class ServerInstance: f' -jar "{file_name}" nogui' ) server_obj.execution_command = execution_command - Console.debug("SUCCESS! Forge install completed") + Console.debug(SUCCESSMSG) except: logger.debug("Could not find run file.") # TODO Use regex to get version and rebuild simple execution From fc308d898581cd1f06bca38d0e31b24c22ee3bf9 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 19:02:09 +0000 Subject: [PATCH 19/84] Update changelog !690 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index c2432de2..66552821 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ - Use Papermc Group's API for `paper` & `folia` builds in server builder ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/688)) ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) +- Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) ### Lang From d9682fdf8f6a87631a88c630037c1039cc3089eb Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 19:15:06 +0000 Subject: [PATCH 20/84] Update changelog !691 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 66552821..1799d83e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) +- Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) ### Lang From a65d5c197cef5bd3c54567389e743b088c78bfbc Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 19:26:54 +0000 Subject: [PATCH 21/84] Update changelog !692 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1799d83e..ad19666d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## --- [4.2.3] - 2023/TBD ### New features - Use Papermc Group's API for `paper` & `folia` builds in server builder ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/688)) +- Allow omission of player count from Dashboard (e.g. for proxy servers) ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/692)) ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) From a502f08946b8014fa37465fdf62f65ece636d362 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 19:37:50 +0000 Subject: [PATCH 22/84] Update changelog !693 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad19666d..33e1d35c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ - Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) +- Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) ### Lang TBD

From e57290a600b5a56924493241009351b560466b50 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 19:48:01 +0000 Subject: [PATCH 23/84] Update changelog !689 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 33e1d35c..1bcb4fa3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) - Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) +- Fix unicode chars in terminal w/ textiowrapper ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/689)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) - Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) From 6d6c613fef0a3295f5a56325f796a99c4fe16d37 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Tue, 16 Jan 2024 20:00:28 +0000 Subject: [PATCH 24/84] Update changelog !689 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1bcb4fa3..35257c29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,7 +7,7 @@ - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) - Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) -- Fix unicode chars in terminal w/ textiowrapper ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/689)) +- Fix unicode chars in terminal & logs w/ textiowrapper ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/689)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) - Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) From 3d4153f941a5a6460abe18db178b1edfc7203ee8 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 15:36:14 -0500 Subject: [PATCH 25/84] Add lockout user for forgot password Hide lockout user from users list --- app/classes/controllers/users_controller.py | 43 +++++++++++++++++++ app/classes/models/users.py | 4 +- app/classes/web/base_handler.py | 6 ++- app/classes/web/routes/api/api_handlers.py | 6 +++ .../routes/api/crafty/antilockout/index.py | 24 +++++++++++ app/frontend/templates/public/login.html | 21 ++++++++- main.py | 2 + 7 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 app/classes/web/routes/api/crafty/antilockout/index.py diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index 87cc513c..510c562e 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -1,5 +1,9 @@ import logging import typing as t +import datetime +import os +import json +from apscheduler.schedulers.background import BackgroundScheduler from app.classes.models.servers import HelperServers from app.classes.models.users import HelperUsers @@ -22,6 +26,7 @@ class UsersController: self.helper = helper self.users_helper = users_helper self.authentication = authentication + self.scheduler = BackgroundScheduler(timezone="Etc/UTC") _permissions_props = { "name": { @@ -353,3 +358,41 @@ class UsersController: def delete_user_api_key(self, key_id: str): return self.users_helper.delete_user_api_key(key_id) + + # ********************************************************************************** + # Lockout Methods + # ********************************************************************************** + def start_anti_lockout(self, app_dir): + lockout_pass = self.helper.create_pass() + self.users_helper.add_user( + "anti-lockout-user", + None, + password=lockout_pass, + email="", + enabled=True, + superuser=True, + theme="ronald", + ) + with open( + os.path.join(app_dir, "app", "config", "anti-lockout.txt"), + "w", + encoding="utf-8", + ) as cred_file: + cred_file.write( + json.dumps( + {"username": "anti-lockout-user", "password": lockout_pass}, + indent=4, + ) + ) + os.chmod(os.path.join(app_dir, "app", "config", "anti-lockout.txt"), 0o600) + self.scheduler.add_job( + self.stop_anti_lockout, + "interval", + hours=1, + id="anti-lockout-watcher", + start_date=datetime.datetime.now(), + ) + + def stop_anti_lockout(self): + self.scheduler.remove_all_jobs() + self.users_helper.remove_user(self.get_id_by_name("anti-lockout-user")) diff --git a/app/classes/models/users.py b/app/classes/models/users.py index ccd8f1b0..e44d06fb 100644 --- a/app/classes/models/users.py +++ b/app/classes/models/users.py @@ -103,7 +103,9 @@ class HelperUsers: @staticmethod def get_all_users(): - query = Users.select().where(Users.username != "system") + query = Users.select().where( + Users.username != "system", Users.username != "anti-lockout-user" + ) return query @staticmethod diff --git a/app/classes/web/base_handler.py b/app/classes/web/base_handler.py index d8181b94..ad490c2f 100644 --- a/app/classes/web/base_handler.py +++ b/app/classes/web/base_handler.py @@ -12,6 +12,7 @@ from app.classes.shared.file_helpers import FileHelpers from app.classes.shared.main_controller import Controller from app.classes.shared.translation import Translation from app.classes.shared.main_models import DatabaseShortcuts +from app.classes.models.users import DoesNotExist logger = logging.getLogger(__name__) auth_log = logging.getLogger("auth") @@ -91,7 +92,10 @@ class BaseHandler(tornado.web.RequestHandler): t.Dict[str, t.Any]: The token's payload. t.Dict[str, t.Any]: The user's data from the database. """ - return self.controller.authentication.check(self.get_cookie("token")) + try: + return self.controller.authentication.check(self.get_cookie("token")) + except DoesNotExist: + return None def autobleach(self, name, text): for r in self.redactables: diff --git a/app/classes/web/routes/api/api_handlers.py b/app/classes/web/routes/api/api_handlers.py index 706c346f..21c78c04 100644 --- a/app/classes/web/routes/api/api_handlers.py +++ b/app/classes/web/routes/api/api_handlers.py @@ -79,6 +79,7 @@ from app.classes.web.routes.api.crafty.stats.stats import ApiCraftyHostStatsHand from app.classes.web.routes.api.crafty.clogs.index import ApiCraftyLogIndexHandler from app.classes.web.routes.api.crafty.imports.index import ApiImportFilesIndexHandler from app.classes.web.routes.api.crafty.exe_cache import ApiCraftyJarCacheIndexHandler +from app.classes.web.routes.api.crafty.antilockout.index import ApiCraftyLockoutHandler def api_handlers(handler_args): @@ -94,6 +95,11 @@ def api_handlers(handler_args): ApiAuthInvalidateTokensHandler, handler_args, ), + ( + r"/api/v2/crafty/resetPass/?", + ApiCraftyLockoutHandler, + handler_args, + ), ( r"/api/v2/crafty/announcements/?", ApiAnnounceIndexHandler, diff --git a/app/classes/web/routes/api/crafty/antilockout/index.py b/app/classes/web/routes/api/crafty/antilockout/index.py new file mode 100644 index 00000000..099f5a47 --- /dev/null +++ b/app/classes/web/routes/api/crafty/antilockout/index.py @@ -0,0 +1,24 @@ +import logging +from app.classes.web.base_api_handler import BaseApiHandler + +logger = logging.getLogger(__name__) + + +class ApiCraftyLockoutHandler(BaseApiHandler): + def get(self): + if self.controller.users.get_id_by_name("anti-lockout-user"): + return self.finish_json( + 425, {"status": "error", "data": "Lockout recovery already in progress"} + ) + self.controller.users.start_anti_lockout(self.controller.project_root) + lockout_msg = ( + "Lockout account has been activated for 1 hour." + " Please find credentials in confg/anti-lockout.txt" + ) + return self.finish_json( + 200, + { + "status": "ok", + "data": lockout_msg, + }, + ) diff --git a/app/frontend/templates/public/login.html b/app/frontend/templates/public/login.html index f66b6c53..1b39d8c4 100644 --- a/app/frontend/templates/public/login.html +++ b/app/frontend/templates/public/login.html @@ -112,8 +112,8 @@
 
- {{ translate('login', 'forgotPassword', - data['lang']) }} +
@@ -146,6 +146,7 @@ + + \ No newline at end of file diff --git a/main.py b/main.py index 75997247..ebaf7806 100644 --- a/main.py +++ b/main.py @@ -388,6 +388,8 @@ if __name__ == "__main__": # Master config.json in helpers.py Console.info("Checking for remote changes to config.json") controller.get_config_diff() + # Delete anti-lockout-user + controller.users.stop_anti_lockout() Console.info("Remote change complete.") # startup the web server From d82ee0fa3160e0272b4f8b434b6a61f9aacf5719 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 18:01:22 -0500 Subject: [PATCH 26/84] start schedule --- app/classes/controllers/users_controller.py | 1 + 1 file changed, 1 insertion(+) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index 510c562e..bc143c31 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -27,6 +27,7 @@ class UsersController: self.users_helper = users_helper self.authentication = authentication self.scheduler = BackgroundScheduler(timezone="Etc/UTC") + self.scheduler.start() _permissions_props = { "name": { From ba8737f007210065b032816175b63069b5908ed7 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 19:21:00 -0500 Subject: [PATCH 27/84] Refactor subpage perm checks Fix bug where subpages people don't still have access to are retained --- app/classes/web/panel_handler.py | 150 +++++++++---------------------- 1 file changed, 43 insertions(+), 107 deletions(-) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 8ac827c3..868bd5a3 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -28,6 +28,17 @@ from app.classes.web.base_handler import BaseHandler from app.classes.web.webhooks.webhook_factory import WebhookFactory logger = logging.getLogger(__name__) +SUBPAGE_PERMS = { + "term": EnumPermissionsServer.TERMINAL, + "logs": EnumPermissionsServer.LOGS, + "schedules": EnumPermissionsServer.SCHEDULE, + "backup": EnumPermissionsServer.BACKUP, + "files": EnumPermissionsServer.FILES, + "config": EnumPermissionsServer.CONFIG, + "admin_controls": EnumPermissionsServer.PLAYERS, + "metrics": EnumPermissionsServer.LOGS, + "webhooks": EnumPermissionsServer.CONFIG, +} class PanelHandler(BaseHandler): @@ -138,6 +149,11 @@ class PanelHandler(BaseHandler): # increasing and will eat up the RAM del chunk + def check_subpage_perms(self, user_perms, subpage): + if SUBPAGE_PERMS.get(subpage, False) in user_perms: + return True + return False + def check_server_id(self): server_id = self.get_argument("id", None) @@ -489,8 +505,17 @@ class PanelHandler(BaseHandler): server_id = self.check_server_id() # load page the user was on last server_subpage = self.controller.servers.server_subpage.get(server_id, "") - if subpage == "" and server_subpage != "": - subpage = self.controller.servers.server_subpage.get(server_id, "") + if ( + subpage == "" + and server_subpage != "" + and self.check_subpage_perms( + self.controller.server_perms.get_user_id_permissions_list( + exec_user["user_id"], server_id + ), + server_subpage, + ) + ): + subpage = server_subpage else: self.controller.servers.server_subpage[server_id] = subpage if server_id is None: @@ -502,16 +527,6 @@ class PanelHandler(BaseHandler): page_data["backup_failed"] = server_obj.last_backup_status() server_obj = None - valid_subpages = [ - "term", - "logs", - "backup", - "config", - "files", - "admin_controls", - "schedules", - "metrics", - ] if not self.failed_server: server = self.controller.servers.get_server_instance_by_id(server_id) # server_data isn't needed since the server_stats also pulls server data @@ -577,7 +592,6 @@ class PanelHandler(BaseHandler): page_data["get_players"] = server.get_server_players() else: page_data["get_players"] = [] - page_data["active_link"] = subpage page_data["permissions"] = { "Commands": EnumPermissionsServer.COMMANDS, "Terminal": EnumPermissionsServer.TERMINAL, @@ -601,83 +615,33 @@ class PanelHandler(BaseHandler): page_data["server_stats"][ "server_type" ] = self.controller.servers.get_server_type_by_id(server_id) - if subpage not in valid_subpages: - logger.debug("not a valid subpage") + if not subpage: - if ( - page_data["permissions"]["Terminal"] - in page_data["user_permissions"] - ): - subpage = "term" - elif page_data["permissions"]["Logs"] in page_data["user_permissions"]: - subpage = "logs" - elif ( - page_data["permissions"]["Schedule"] - in page_data["user_permissions"] - ): - subpage = "schedules" - elif ( - page_data["permissions"]["Backup"] in page_data["user_permissions"] - ): - subpage = "backup" - elif page_data["permissions"]["Files"] in page_data["user_permissions"]: - subpage = "files" - elif ( - page_data["permissions"]["Config"] in page_data["user_permissions"] - ): - subpage = "config" - elif ( - page_data["permissions"]["Players"] in page_data["user_permissions"] - ): - subpage = "admin_controls" - else: + for spage, perm in SUBPAGE_PERMS.items(): + if perm in page_data["user_permissions"]: + subpage = spage + break + # If we still don't have a subpage we're going to assume they + # have no perms + if not subpage: self.redirect("/panel/error?error=Unauthorized access to Server") + page_data["active_link"] = subpage logger.debug(f'Subpage: "{subpage}"') - if subpage == "term": - if ( - not page_data["permissions"]["Terminal"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect( - "/panel/error?error=Unauthorized access to Terminal" - ) - return - - if subpage == "logs": - if ( - not page_data["permissions"]["Logs"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect("/panel/error?error=Unauthorized access to Logs") - return + if ( + not self.check_subpage_perms(page_data["user_permissions"], subpage) + and not superuser + ): + return self.redirect( + f"/panel/error?error=Unauthorized access to {subpage}" + ) if subpage == "schedules": - if ( - not page_data["permissions"]["Schedule"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect( - "/panel/error?error=Unauthorized access To Schedules" - ) - return page_data["schedules"] = HelpersManagement.get_schedules_by_server( server_id ) if subpage == "config": - if ( - not page_data["permissions"]["Config"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect( - "/panel/error?error=Unauthorized access Server Config" - ) - return page_data["java_versions"] = Helpers.find_java_installs() server_obj: Servers = self.controller.servers.get_server_obj(server_id) page_data["failed"] = self.failed_server @@ -691,26 +655,7 @@ class PanelHandler(BaseHandler): page_java.append(version) page_data["java_versions"] = page_java - - if subpage == "files": - if ( - not page_data["permissions"]["Files"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect("/panel/error?error=Unauthorized access Files") - return - if subpage == "backup": - if ( - not page_data["permissions"]["Backup"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect( - "/panel/error?error=Unauthorized access to Backups" - ) - return server_info = self.controller.servers.get_server_data_by_id(server_id) page_data[ "backup_config" @@ -761,15 +706,6 @@ class PanelHandler(BaseHandler): server_id, hours=(days * 24) ) if subpage == "webhooks": - if ( - not page_data["permissions"]["Config"] - in page_data["user_permissions"] - ): - if not superuser: - self.redirect( - "/panel/error?error=Unauthorized access to Webhooks Config" - ) - return page_data[ "webhooks" ] = self.controller.management.get_webhooks_by_server( From f800933799a04fd9f85ef8009b41e29cf5123843 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Tue, 16 Jan 2024 23:09:04 -0500 Subject: [PATCH 28/84] Fix typo --- app/classes/web/routes/api/crafty/antilockout/index.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/web/routes/api/crafty/antilockout/index.py b/app/classes/web/routes/api/crafty/antilockout/index.py index 099f5a47..41493f88 100644 --- a/app/classes/web/routes/api/crafty/antilockout/index.py +++ b/app/classes/web/routes/api/crafty/antilockout/index.py @@ -13,7 +13,7 @@ class ApiCraftyLockoutHandler(BaseApiHandler): self.controller.users.start_anti_lockout(self.controller.project_root) lockout_msg = ( "Lockout account has been activated for 1 hour." - " Please find credentials in confg/anti-lockout.txt" + " Please find credentials in config/anti-lockout.txt" ) return self.finish_json( 200, From 665997c34cb2a42f2e4654b79956e6720a32c309 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Mon, 22 Jan 2024 19:51:57 -0500 Subject: [PATCH 29/84] Print to terminal not file --- app/classes/controllers/users_controller.py | 26 ++++++++----------- .../routes/api/crafty/antilockout/index.py | 4 +-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index bc143c31..eb74f15c 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -1,8 +1,6 @@ import logging import typing as t import datetime -import os -import json from apscheduler.schedulers.background import BackgroundScheduler from app.classes.models.servers import HelperServers @@ -12,6 +10,7 @@ from app.classes.models.crafty_permissions import ( PermissionsCrafty, EnumPermissionsCrafty, ) +from app.classes.shared.console import Console logger = logging.getLogger(__name__) @@ -363,7 +362,7 @@ class UsersController: # ********************************************************************************** # Lockout Methods # ********************************************************************************** - def start_anti_lockout(self, app_dir): + def start_anti_lockout(self): lockout_pass = self.helper.create_pass() self.users_helper.add_user( "anti-lockout-user", @@ -374,18 +373,15 @@ class UsersController: superuser=True, theme="ronald", ) - with open( - os.path.join(app_dir, "app", "config", "anti-lockout.txt"), - "w", - encoding="utf-8", - ) as cred_file: - cred_file.write( - json.dumps( - {"username": "anti-lockout-user", "password": lockout_pass}, - indent=4, - ) - ) - os.chmod(os.path.join(app_dir, "app", "config", "anti-lockout.txt"), 0o600) + + Console.yellow( + f""" + Anti-lockout recovery account enabled! + {'/' * 74} + Username: anti-lockout-user + Password: {lockout_pass} + {'/' * 74}""" + ) self.scheduler.add_job( self.stop_anti_lockout, "interval", diff --git a/app/classes/web/routes/api/crafty/antilockout/index.py b/app/classes/web/routes/api/crafty/antilockout/index.py index 41493f88..0a9ab03a 100644 --- a/app/classes/web/routes/api/crafty/antilockout/index.py +++ b/app/classes/web/routes/api/crafty/antilockout/index.py @@ -10,10 +10,10 @@ class ApiCraftyLockoutHandler(BaseApiHandler): return self.finish_json( 425, {"status": "error", "data": "Lockout recovery already in progress"} ) - self.controller.users.start_anti_lockout(self.controller.project_root) + self.controller.users.start_anti_lockout() lockout_msg = ( "Lockout account has been activated for 1 hour." - " Please find credentials in config/anti-lockout.txt" + " Please find temporary credentials in the terminal" ) return self.finish_json( 200, From fc93b6f6a1c31b51014a8df30ddd5a0d9b263c5b Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 26 Jan 2024 11:50:34 -0500 Subject: [PATCH 30/84] Add Thai, Turkish, Ukranian languages --- app/translations/en_EN.json | 6 +- app/translations/th_TH.json | 668 ++++++++++++++++++++++++++++++++++++ app/translations/tr_TR.json | 668 ++++++++++++++++++++++++++++++++++++ app/translations/uk_UA.json | 668 ++++++++++++++++++++++++++++++++++++ 4 files changed, 2007 insertions(+), 3 deletions(-) create mode 100644 app/translations/th_TH.json create mode 100644 app/translations/tr_TR.json create mode 100644 app/translations/uk_UA.json diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index a717c929..32721082 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Please be patient while we remove your server from the Crafty panel and delete all files. This screen will close in a few moments.", "bePatientUpdate": "Please be patient while we update the server. Download times can vary depending upon your internet speeds.
This screen will refresh in a moment", "cancel": "Cancel", + "countPlayers": "Include server in total player count", "crashTime": "Crash Timeout", "crashTimeDesc": "How long should we wait before we consider your server as crashed?", "deleteFilesQuestion": "Delete server files from machine?", @@ -377,8 +378,7 @@ "timeoutExplain2": "command before it forces the process down.", "update": "Update Executable", "yesDelete": "Yes, delete", - "yesDeleteFiles": "Yes, delete files", - "countPlayers": "Include server in total player count" + "yesDeleteFiles": "Yes, delete files" }, "serverConfigHelp": { "desc": "Here is where you can change the configuration of your server", @@ -666,4 +666,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} \ No newline at end of file +} diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json new file mode 100644 index 00000000..f919236a --- /dev/null +++ b/app/translations/th_TH.json @@ -0,0 +1,668 @@ +{ + "404": { + "contact": "ติดต่อฝ่ายสนับสนุน Crafty Control ผ่านดิสคอร์ด", + "notFound": "Page Not Found", + "unableToFind": "เราไม่พบหน้าที่คุณกำลังมองหา โปรดลองอีกครั้งหรือย้อนกลับและโหลดหน้าเว็บใหม่อีกครั้ง" + }, + "accessDenied": { + "accessDenied": "Access Denied", + "contact": "ติดต่อฝ่ายสนับสนุน Crafty Control ผ่านดิสคอร์ด", + "contactAdmin": "กรุณาติดต่อผู้ดูแลระบบเซิร์ฟเวอร์ของคุณเพื่อเข้าถึงหน้านี้ หรือหากคุณคิดว่าคุณควรมีสิทธิ์เข้าถึงหน้านี้ โปรดติดต่อฝ่ายสนับสนุน", + "noAccess": "คุณไม่ได้รับอนุญาติให้เข้าถึงหน้านี้" + }, + "apiKeys": { + "apiKeys": "คีย์ API", + "auth": "ให้สิทธิ์อนุญาต? ", + "buttons": "ปุ่มคำสั่ง", + "config": "ตั้งค่า", + "crafty": "Crafty: ", + "createNew": "สร้างโทเค็น API ใหม่", + "created": "สร้างเมื่อ", + "deleteKeyConfirmation": "คุณต้องการลบคีย์ API นี้หรือไม่ สิ่งนี้ไม่สามารถยกเลิกได้", + "deleteKeyConfirmationTitle": "ลบคีย์ API นี้ ${keyId} หรือไม่?", + "getToken": "แสดงโทเค็น", + "name": "ชื่อ", + "nameDesc": "คุณต้องการเรียกโทเค็น API นี้ว่าอะไร ? ", + "no": "ไม่", + "pageTitle": "แก้ไขคีย์ API ของผู้ใช้", + "permName": "ชื่อการอนุญาต", + "perms": "สิทธิ์อนุญาต", + "server": "เซิร์ฟเวอร์: ", + "superUser": "Super User", + "yes": "ใช่" + }, + "base": { + "doesNotWorkWithoutJavascript": "คำเตือน: Crafty จะทำงานไม่ถูกต้องเมื่อไม่ได้เปิดใช้งาน JavaScript!" + }, + "credits": { + "developmentTeam": "ทีมพัฒนา", + "hugeDesc": "ขอ", + "pageDescription": "หากไม่มีบุคคลเหล่านี้ ก็จะไม่มี Crafty ในวันนี้", + "pageTitle": "เครดิต", + "patreonDesc": "ถึงผู้สนับสนุน Patreon / Ko-fi ของเรา!", + "patreonOther": "อื่นๆ", + "patreonSupporter": "ผู้สนับสนุน Patreon / Ko-fi", + "patreonUpdate": "อัปเดตล่าสุด:", + "retiredStaff": "อดีตทีมงาน", + "subscriberName": "ชื่อ", + "subscriptionLevel": "ระดับ", + "supportTeam": "ทีมสนับสนุนและจัดทำเอกสาร", + "thankYou": "ขอบคุณจากหัวใจ", + "translationDesc": "ถึงชุมชนของเราที่ช่วยแปล! [ ยังคงทำงานอยู่ = 🟢 ไม่ได้ทำงานแล้ว/อดีตทีมงาน = ⚪ ]", + "translationName": "ภาษา", + "translationTitle": "ทีมแปลภาษา", + "translator": "ผู้แปล" + }, + "customLogin": { + "apply": "นำไปใช้", + "backgroundUpload": "อัปโหลดภาพพื้นหลัง", + "customLoginPage": "ปรับแต่งหน้าเข้าสู่ระบบ", + "delete": "ลบ", + "labelLoginImage": "เลือกรูปพื้นหลังหน้าเข้าสู่ระบบของคุณ", + "loginBackground": "รูปพื้นหลังหน้าเข้าสู่ระบบ", + "loginImage": "อัปโหลดภาพพื้นหลังสำหรับหน้าเข้าสู่ระบบ", + "loginOpacity": "เลือกความทึบของหน้าต่างเข้าสู่ระบบ", + "pageTitle": "หน้าเข้าสู่ระบบที่กำหนดเอง", + "preview": "ดูตัวอย่าง", + "select": "เลือก", + "selectImage": "เลือกรูปภาพ" + }, + "dashboard": { + "actions": "คำสั่งด่วน", + "allServers": "เซิร์ฟเวอร์ทั้งหมด", + "avg": "ค่าเฉลี่ย", + "backups": "สำรองข้อมูล", + "bePatientClone": "กรุณารออย่างใจเย็นในขณะที่เราโคลนเซิร์ฟเวอร์
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", + "bePatientRestart": "กรุณารออย่างใจเย็นในขณะที่เรารีสตาร์ทเซิร์ฟเวอร์
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", + "bePatientStart": "กรุณารออย่างใจเย็นในขณะที่เรากำลังเริ่มเซิร์ฟเวอร์
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", + "bePatientStop": "กรุณารออย่างใจเย็นในขณะที่เราหยุดการทำงานเซิร์ฟเวอร์
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", + "cannotSee": "ไม่เห็นอะไรเลยใช่ใหม?", + "cannotSeeOnMobile": "ไม่เห็นอะไรในโทรศัพท์เลยใช่ใหม่?", + "cannotSeeOnMobile2": "ลองเลื่อนไปด้านข้างดูสิ", + "clone": "โคลนเซิร์ฟเวอร์", + "cloneConfirm": "คุณแน่ใจหรือไม่ว่าต้องการโคลนเซิร์ฟเวอร์นี้? กระบวนการนี้อาจใช้เวลาสักครู่", + "cpuCores": "คอร์ CPU", + "cpuCurFreq": "CPU Clock ปัจจุบัน", + "cpuMaxFreq": "CPU Clock สูงสุด", + "cpuUsage": "การใช้งาน CPU", + "crashed": "ล้มเหลว", + "dashboard": "แผงควบคุม", + "delay-explained": "บริการ/ตัวแทนเพิ่งเริ่มต้นและกำลังชะลอการเริ่มต้นเซิร์ฟเวอร์ Minecraft", + "host": "โฮส", + "installing": "กำลังติดตั้ง...", + "kill": "บังคับหยุดการทำงาน", + "killing": "กำลังหยุดการทำงาน...", + "lastBackup": "ล่าสุด:", + "max": "เต็ม", + "memUsage": "การใช้งาน RAM", + "motd": "MOTD", + "newServer": "สร้างเซิร์ฟเวอร์ใหม่", + "nextBackup": "ต่อไป:", + "no-servers": "ไม่มีเซิร์ฟเวอร์ขณะนี้ ถ้าต้องการเริ่มต้น, กดที่", + "offline": "ออฟไลน์", + "online": "ออนไลน์", + "players": "จำนวนผู้เล่น", + "restart": "รีสตาร์ท", + "sendingCommand": "กำลังส่งคำสั่งของคุณ", + "server": "เซิร์ฟเวอร์", + "servers": "เซิร์ฟเวอร์", + "size": "ขนาดเซิร์ฟเวอร์", + "start": "เริ่มการทำงาน", + "starting": "ชะลอการเริ่มต้น", + "status": "สถานะเซิร์ฟเวอร์", + "stop": "หยุดการทำงาน", + "storage": "พื้นที่จัดเก็บ", + "version": "เวอร์ชั่น", + "welcome": "ยินดีต้อนรับสู่ Crafty Controller" + }, + "datatables": { + "i18n": { + "aria": { + "sortAscending": ": เปิดใช้งานเพื่อเรียงลำดับคอลัมน์จากน้อยไปมาก", + "sortDescending": ": เปิดใช้งานเพื่อเรียงลำดับคอลัมน์จากมากไปน้อย" + }, + "buttons": { + "collection": "Collection ", + "colvis": "การมองเห็นคอลัมน์", + "colvisRestore": "คืนค่าการมองเห็น", + "copy": "คัดลอก", + "copyKeys": "กด Ctrl หรือ u2318 + C เพื่อคัดลอกข้อมูลตารางไปยังคลิปบอร์ดของระบบ

หากต้องการยกเลิก ให้คลิกข้อความนี้หรือกด Escape", + "copySuccess": { + "1": "คัดลอก 1 แถวไปยังคลิปบอร์ดแล้ว", + "_": "คัดลอก %d แถวไปยังคลิปบอร์ดแล้ว" + }, + "copyTitle": "คัดลอกไปยังคลิปบอร์ด", + "csv": "CSV", + "excel": "Excel", + "pageLength": { + "-1": "แสดงทุกแถว", + "1": "แสดง 1 แถว", + "_": "แสดง %d แถว" + }, + "pdf": "PDF", + "print": "Print" + }, + "decimal": "", + "emptyTable": "ไม่มีข้อมูลในตาราง", + "info": "แสดงรายการ _START_ ถึง _END_ จากทั้งหมด _TOTAL_ รายการ", + "infoEmpty": "แสดงรายการ 0 ถึง 0 จากทั้งหมด 0 รายการ", + "infoFiltered": "(กรองจากรายการทั้งหมด _MAX_ รายการ)", + "infoPostFix": "", + "lengthMenu": "แสดง _MENU_ รายการ", + "loadingRecords": "กำลังโหลด...", + "paginate": { + "first": "หน้าแรก", + "last": "หน้าสุดท้าย", + "next": "หน้าต่อไป", + "previous": "หน้าก่อนหน้า" + }, + "processing": "กำลังประมวลผล...", + "search": "ค้นหา:", + "select": { + "cells": { + "0": "คลิกที่เซลเพื่อเลือก", + "1": "เลือก %d เซลล์แล้ว", + "_": "เลือก %d เซลล์แล้ว" + }, + "columns": { + "0": "คลิกที่คอลัมน์เพื่อเลือก", + "1": "เลือก %d คอลัมน์แล้ว", + "_": "เลือก %d คอลัมน์แล้ว" + }, + "rows": { + "0": "คลิกที่แถวเพื่อเลือก", + "1": "เลือก %d แถวแล้ว", + "_": "เลือก %d แถวแล้ว" + } + }, + "thousands": ",", + "zeroRecords": "ไม่พบรายการที่ตรงกัน" + } + }, + "error": { + "agree": "ยอมรับ", + "bedrockError": "การดาวน์โหลดเวอร์ชั่น Bedrock ไม่พร้อมใช้งาน โปรดตรวจสอบ", + "cancel": "ยกเลิก", + "contact": "ติดต่อฝ่ายสนับสนุน Crafty Control ผ่านดิสคอร์ด", + "craftyStatus": "หน้าสถานะของ Crafty", + "cronFormat": "ตรวจพบรูปแบบครอนที่ไม่ถูกต้อง", + "embarassing": "โอ้ย นี่มันน่าอายชะมัด", + "error": "Error!", + "eulaAgree": "คุณเห็นด้วยหรือไม่?", + "eulaMsg": "คุณต้องเห็นด้วยกับ ", + "eulaTitle": "เห็นด้วยกับ EULA", + "fileError": "ประเภทไฟล์ต้องเป็นรูปภาพ", + "fileTooLarge": "การอัปโหลดล้มเหลว. ไฟล์ที่อัปโหลดมีขนาดใหญ่เกินไป ติดต่อผู้ดูแลระบบเพื่อขอความช่วยเหลือ", + "hereIsTheError": "นี่คือข้อผิดพลาด", + "installerJava": "ไม่สามารถติดตั้ง {} : การติดตั้ง Forge Server ต้องใช้ Java เราตรวจพบว่าคุณไม่ได้ติดตั้ง Java กรุณาติดตั้ง Java จากนั้นติดตั้งเซิร์ฟเวอร์อีกครั้ง", + "internet": "เราตรวจพบว่าเครื่องที่ใช้งาน Crafty ไม่มีการเชื่อมต่ออินเทอร์เน็ต การเชื่อมต่อผู้ใช้กับเซิร์ฟเวอร์อาจถูกจำกัด", + "migration": "พื้นที่เก็บข้อมูลเซิร์ฟเวอร์หลักของ Crafty กำลังถูกย้ายไปยังตำแหน่งใหม่ การเริ่มต้นเซิร์ฟเวอร์ทั้งหมดถูกระงับในช่วงเวลานี้ โปรดรอในขณะที่เราย้ายข้อมูลนี้ให้เสร็จสิ้น", + "no-file": "ดูเหมือนเราจะไม่พบไฟล์ที่ร้องขอ ตรวจสอบเส้นทางอีกครั้ง, Crafty เข้าถึงสิทธิ์ที่เหมาะสมหรือไม่?", + "noInternet": "Crafty ประสบปัญหาในการเข้าถึงอินเทอร์เน็ต การสร้างเซิร์ฟเวอร์ถูกปิดใช้งาน โปรดตรวจสอบการเชื่อมต่ออินเทอร์เน็ตของคุณและโหลดหน้านี้ใหม่อีกครั้ง", + "noJava": "เซิร์ฟเวอร์ {} ไม่สามารถเริ่มต้นได้เนื่องจากรหัสข้อผิดพลาด: เราตรวจพบว่าคุณไม่ได้ติดตั้ง Java กรุณาติดตั้ง Java จากนั้นเริ่มเซิร์ฟเวอร์ใหม่อีกครั้ง", + "not-downloaded": "ดูเหมือนว่าเราจะไม่พบแฟ้มกระทำการของคุณ (.jar) ตรวจสอบให้แน่ใจว่าการดาวโหลดน์เสร็จสิ้นแล้ว, การอนุญาตถูกตั้งไปยังแฟ้มกระทำการหรือไม่?", + "portReminder": "เราตรวจพบว่านี่เป็นครั้งแรกที่มีการเรียกใช้ {} ตรวจสอบให้แน่ใจว่าได้ Forward port {} ผ่านเราเตอร์/ไฟร์วอลล์ของคุณเพื่อให้สามารถเข้าถึงได้จากอินเทอร์เน็ตจากระยะไกล", + "privMsg": "และ ", + "serverJars1": "ไม่สามารถเข้าถึงเซิร์ฟเวอร์ JARs API กรุณาตรวจสอบ", + "serverJars2": "เพื่อข้อมูลที่ทันสมัยที่สุด", + "start-error": "เซิร์ฟเวอร์ {} ไม่สามารถเริ่มต้นได้เนื่องจากรหัสข้อผิดพลาด: {}", + "superError": "คุณต้องเป็น Super User จึงจะดำเนินการนี้ได้", + "terribleFailure": "นี่มันเป็นความล้มเหลวครั้งยิ่งใหญ่!" + }, + "footer": { + "allRightsReserved": "สงวนลิขสิทธิ์ทั้งหมด", + "copyright": "ลิขสิทธิ์ของ", + "version": "เวอร์ชั่น" + }, + "login": { + "forgotPassword": "ลืมรหัสผ่าน", + "login": "เข้าสู่ระบบ", + "password": "รหัสผ่าน", + "username": "ชื่อผู้ใช้", + "viewStatus": "ดูหน้าสถานะเซิร์ฟเวอร์แบบสาธารณะ" + }, + "notify": { + "activityLog": "บันทึกกิจกรรม", + "backupComplete": "การสำรองข้อมูลเสร็จสมบูรณ์สำหรับเซิร์ฟเวอร์ {}", + "backupStarted": "เริ่มต้นการสำรองข้อมูลสำหรับเซิร์ฟเวอร์ {}", + "downloadLogs": "ต้องการดาวน์โหลดบันทึกการสนับสนุนไหม?", + "finishedPreparing": "เราได้เตรียมบันทึกการสนับสนุนของคุณเสร็จแล้ว กรุณาคลิกดาวน์โหลดเพื่อดาวน์โหลด", + "logout": "ออกจากระบบ", + "preparingLogs": " โปรดรอสักครู่ในขณะที่เราเตรียมบันทึกของคุณ... เราจะส่งการแจ้งเตือนเมื่อเสร็จสิ้น การดำเนินการนี้อาจใช้เวลาสักครู่สำหรับการเตรียมข้อมูลขนาดใหญ่", + "supportLogs": "บันทึกการสนับสนุน" + }, + "offline": { + "offline": "ออฟไลน์", + "pleaseConnect": "กรุณาเชื่อมต่ออินเทอร์เน็ตเพื่อใช้ Crafty" + }, + "panelConfig": { + "adminControls": "การควบคุมผู้ดูแล", + "allowedServers": "เซิร์ฟเวอร์ที่ได้รับอนุญาต", + "apply": "ยืนยัน", + "assignedRoles": "บทบาทที่ได้รับมอบหมาย", + "cancel": "ยกเลิก", + "clearComms": "ล้างคำสั่งที่ยังไม่ได้ดำเนินการ", + "custom": "ปรับแต่ง Crafty", + "delete": "ลบ", + "edit": "แก้ไข", + "enableLang": "เปิดใช้งานภาษาทั้งหมด", + "enabled": "เปิด", + "globalExplain": "พิ้นที่ที่ Crafty เก็บไฟล์เซิร์ฟเวอร์ทั้งหมดของคุณ (เราจะต่อท้ายเส้นทางด้วย /servers/[uuid ของเซิร์ฟเวอร์])", + "globalServer": "พิ้นที่เก็บข้อมูลหลัก", + "json": "Config.json", + "match": "รหัสผ่านต้องตรงกัน", + "newRole": "เพิ่มบทบาทใหม่", + "newUser": "เพิ่มผู้ใช้ใหม่", + "noMounts": "ไม่แสดงพื้นที่จัดเก็บบนแผงควบคุม", + "pageTitle": "ตั้งค่าแผงควบคุม", + "role": "ชื่อบทบาท", + "roleUsers": "สมาชิคบทบาท", + "roles": "บทบาท", + "save": "บันทึก", + "select": "เลือก", + "superConfirm": "ดำเนินการต่อเฉพาะในกรณีที่คุณต้องการให้ผู้ใช้รายนี้สามารถเข้าถึงทุกสิ่งได้ (บัญชีผู้ใช้ทั้งหมด เซิร์ฟเวอร์ การตั้งค่าแผงควบคุม ฯลฯ) พวกเขายังสามารถเพิกถอนสิทธิ์ Super User ของคุณได้", + "superConfirmTitle": "ให้สิทธิ์ Super User? คุณแน่ใจแล้วใช่ไหม?", + "title": "การตั้งค่า Crafty", + "user": "ชื่อผู้ใช้", + "users": "ผู้ใช้" + }, + "rolesConfig": { + "config": "แก้ไขบทบาท", + "configDesc": "คุณสามารถเปลี่ยนแปลงการตั้งค่าบทบาทของคุณได้ที่นี่", + "configUpdate": "อัปเดตล่าสุด: ", + "created": "สร้างเมื่อ: ", + "delRole": "ลบบทบาท", + "doesNotExist": "คุณไม่สามารถลบสิ่งที่ยังไม่มีได้", + "pageTitle": "แก้ไขบทบาท", + "pageTitleNew": "บทบาทใหม่", + "permAccess": "เข้าถึง?", + "permName": "ชื่อการอนุญาต", + "permsServer": "สิทธิ์ที่บทบาทนี้มีสำหรับเซิร์ฟเวอร์ที่ระบุนี้", + "roleConfigArea": "พื้นที่ตั้งค่าบทบาท", + "roleDesc": "คุณอยากจะเรียกบทบาทนี้ว่าอะไร?", + "roleName": "ชื่อบทบาท: ", + "rolePerms": "สิทธิ์ของบทบาท", + "roleServers": "เซิร์ฟเวอร์ที่ได้รับอนุญาต", + "roleTitle": "การตั้งค่าบทบาท", + "roleUserName": "ชื่อผู้ใช้", + "roleUsers": "ผู้ใช้บทบาท: ", + "selectManager": "เลือกผู้จัดการสำหรับบทบาทนี้", + "serverAccess": "ให้สิทธิ์การเข้าถึง", + "serverName": "ชื่อเซิร์ฟเวอร์", + "serversDesc": "เซิร์ฟเวอร์ที่บทบาทนี้ได้รับอนุญาตให้เข้าถึง" + }, + "serverBackups": { + "after": "ส่งคำสั่งหลังการสำรองข้อมูล", + "backupAtMidnight": "คุณต้องการสำรองข้อมูลอัตโนมัติตอนเที่ยงคืนหรือไม่?", + "backupNow": "สำรองข้อมูลตอนนี้!", + "backupTask": "เริ่มการสำรองข้อมูลแล้ว", + "before": "ส่งคำสั่งก่อนการสำรองข้อมูล", + "cancel": "ยกเลิก", + "clickExclude": "คลิกเพื่อเลือกการยกเว้น", + "compress": "บีบอัดข้อมูลสำรอง", + "confirm": "ยืนยัน", + "confirmDelete": "คุณต้องการลบข้อมูลสำรองนี้หรือไม่ สิ่งนี้ไม่สามารถยกเลิกได้", + "confirmRestore": "คุณแน่ใจหรือไม่ว่าต้องการกู้คืนจากข้อมูลสำรองนี้ ไฟล์เซิร์ฟเวอร์ปัจจุบันทั้งหมดจะเปลี่ยนเป็นแบบสำรองและจะไม่สามารถกู้คืนได้", + "currentBackups": "ไฟล์สำรองข้อมูลปัจจุบัน", + "delete": "ลบ", + "destroyBackup": "คุณต้องการทำลายข้อมูลสำรอง \" + file_to_del + \"หรือไม่", + "download": "ดาวน์โหลด", + "excludedBackups": "เส้นทางที่ยกเว้น: ", + "excludedChoose": "เลือกเส้นทางที่คุณต้องการยกเว้นจากการสำรองข้อมูลของคุณ", + "exclusionsTitle": "ข้อยกเว้นการสำรองข้อมูล", + "maxBackups": "ต้องการเก็บข้อมูลสำรองกี่ครั้ง?", + "maxBackupsDesc": "Crafty จะไม่เก็บข้อมูลสำรองมากกว่า N รายการ โดยจะลบข้อมูลสำรองที่เก่าที่สุด (ป้อน 0 เพื่อเก็บทั้งหมด)", + "options": "ตัวเลือก", + "path": "เส้นทาง", + "restore": "คืนค่า", + "restoring": "กำลังกู้คืนข้อมูลสำรอง การดำเนินการนี้อาจใช้เวลาสักครู่ กรุณาอดทนรออย่างใจเย็น", + "save": "บันทึก", + "shutdown": "ปิดเซิร์ฟเวอร์ตามระยะเวลาของการสำรองข้อมูล", + "size": "ขนาด", + "storageLocation": "สถานที่จัดเก็บ", + "storageLocationDesc": "คุณต้องการสำรองข้อมูลไว้ที่ไหน?" + }, + "serverConfig": { + "bePatientDelete": "กรุณารออย่างใจเย็นในขณะที่เราลบเซิร์ฟเวอร์ของคุณออกจากแผงควบคุม Crafty หน้าต่างนี้จะปิดลงในอีกสักครู่", + "bePatientDeleteFiles": "โปรดอดทนรอในขณะที่เราลบเซิร์ฟเวอร์ของคุณออกจากแผง Crafty และลบไฟล์ทั้งหมด หน้าต่องนี้จะปิดลงในอีกสักครู่", + "bePatientUpdate": "กรุณารออย่างใจเย็นในขณะที่เราอัปเดตเซิร์ฟเวอร์ เวลาในการดาวน์โหลดอาจแตกต่างกันไปขึ้นอยู่กับความเร็วอินเทอร์เน็ตของคุณ
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", + "cancel": "ยกเลิก", + "crashTime": "ผิดพลาด หมดเวลา", + "crashTimeDesc": "เราควรรอนานแค่ไหนก่อนที่จะพิจารณาว่าเซิร์ฟเวอร์ของคุณขัดข้อง?", + "deleteFilesQuestion": "ลบไฟล์เซิร์ฟเวอร์ออกจากเครื่อง?", + "deleteFilesQuestionMessage": "คุณต้องการให้ Crafty ลบไฟล์เซิร์ฟเวอร์ทั้งหมดออกจากเครื่องโฮสต์หรือไม่

ซึ่งรวมถึงข้อมูลสำรองของเซิร์ฟเวอร์ด้วย", + "deleteServer": "ลบเซิร์ฟเวอร์", + "deleteServerQuestion": "ต้องการลบเซิร์ฟเวอร์?", + "deleteServerQuestionMessage": "คุณแน่ใจหรือไม่ว่าต้องการลบเซิร์ฟเวอร์นี้ หลังจากนี้จะไม่มีทางให้หันหลังกลับ...", + "exeUpdateURL": "อัปเดต URL แฟ้มกระทำการ (.jar) ของเซิร์ฟเวอร์", + "exeUpdateURLDesc": "ดาวน์โหลด URL โดยตรงสำหรับการอัปเดต", + "ignoredExits": "ละเว้นรหัสข้อผิดพลาด", + "ignoredExitsExplain": "รหัสข้อผิดพลาดที่ระบบตรวจจับข้อขัดข้องของ Crafty จะละเว้นเป็นการ 'หยุด' ปกติ (คั่นด้วยเครื่องหมายจุลภาค)", + "javaNoChange": "อย่าแทนที่", + "javaVersion": "แทนที่เวอร์ชัน Java ปัจจุบัน", + "javaVersionDesc": "หากคุณกำลังจะแทนที่ Java ตรวจสอบให้แน่ใจว่าเส้นทาง Java ปัจจุบันของคุณใน 'คำสั่งการดำเนินการเซิร์ฟเวอร์' อยู่ในเครื่องหมายคำพูด (ยกเว้นตัวแปร 'java' เริ่มต้น)", + "noDelete": "ไม่, ย้อนกลับ", + "noDeleteFiles": "ไม่, แค่ลบออกจากแผงควบคุม", + "removeOldLogsAfter": "ลบบัททึกเก่าหลังจาก", + "removeOldLogsAfterDesc": "ไฟล์บันทึกจะต้องเก่ากี่วันจึงจะถูกลบ (ปิด 0)", + "save": "บันทึก", + "sendingDelete": "กำลังลบเซิร์ฟเวอร์", + "sendingRequest": "กำลังส่งคำขอของคุณ...", + "serverAutoStart": "เริ่มการทำงานเซิร์ฟเวอร์โดยอัตโนมัติ", + "serverAutostartDelay": "หน่วงเวลาการเริ่มต้นโดยอัตโนมัติ", + "serverAutostartDelayDesc": "หน่วงเวลาก่อนเริ่มต้นอัตโนมัติ (หากเปิดใช้งานด้านล่าง)", + "serverCrashDetection": "การตรวจจับความผิดพลาดของเซิร์ฟเวอร์", + "serverExecutable": "แฟ้มกระทำการของเซิร์ฟเวอร์", + "serverExecutableDesc": "แฟ้มกระทำการที่ใช้ในการทำงานของเซิร์ฟเวอร์ (.jar)", + "serverExecutionCommand": "คำสั่งการดำเนินการเซิร์ฟเวอร์", + "serverExecutionCommandDesc": "สิ่งนี้จะทำงานเบื้องหลังเทอร์มินัล", + "serverIP": "IP เซิร์ฟเวอร์", + "serverIPDesc": "IP ที่ Crafty ใช้เชื่อมต่อเพื่อดูสถิติ (ลองใช้ IP จริงแทน 127.0.0.1 หากคุณพบปัญหา)", + "serverLogLocation": "ตำแหน่งไฟล์บันทึกข้อมูลเซิร์ฟเวอร์", + "serverLogLocationDesc": "เส้นทางไปยังไฟล์บันทึก", + "serverName": "ชื่อเซิร์ฟเวอร์", + "serverNameDesc": "คุณอยากเรียกเซิร์ฟเวอร์นี้ว่าอะไร", + "serverPath": "โฟลเดอร์การทำงานของเซิร์ฟเวอร์", + "serverPathDesc": "เส้นทางแบบเต็มสัมบูรณ์ (ไม่รวมแฟ้มกระทำการ .jar)", + "serverPort": "พอร์ตเซิร์ฟเวอร์", + "serverPortDesc": "พอร์ตที่ Crafty ใช้เชื่อมต่อเพื่อดูสถิติ", + "serverStopCommand": "คำสั่งหยุดการทำงานเซิร์ฟเวอร์", + "serverStopCommandDesc": "คำสั่งที่ส่งไปยังโปรแกรมเพื่อหยุดการทำงาน", + "showStatus": "แสดงบนหน้าสถานะเซิร์ฟเวอร์", + "shutdownTimeout": "หมดเวลาหยุดการทำงาน", + "statsHint1": "พอร์ตที่เซิร์ฟเวอร์ของคุณทำงานอยู่ควรอยู่ที่นี่ นี่เป็นเพียงวิธีที่ Crafty เปิดการเชื่อมต่อกับเซิร์ฟเวอร์ของคุณเพื่อดูสถิติ", + "statsHint2": "สิ่งนี้จะไม่เปลี่ยนพอร์ตของเซิร์ฟเวอร์ของคุณ คุณยังคงต้องเปลี่ยนพอร์ตในไฟล์กำหนดค่าเซิร์ฟเวอร์ของคุณ", + "stopBeforeDeleting": "กรุณาหยุดเซิร์ฟเวอร์ก่อนที่จะลบมัน", + "timeoutExplain1": "Crafty จะรอให้เซิร์ฟเวอร์ของคุณปิดระบบนานแค่ไหนหลังจากดำเนินการ", + "timeoutExplain2": "คำสั่งก่อนที่จะบังคับให้กระบวนการหยุดทำงาน", + "update": "อัปเดตการดำเนินการ", + "yesDelete": "ใช่, ลบ", + "yesDeleteFiles": "ใช่, ลบไฟล์" + }, + "serverConfigHelp": { + "desc": "ที่นี่คุณสามารถเปลี่ยนการตั้งค่าเซิร์ฟเวอร์ของคุณได้", + "perms": [ + "ขอแนะนำให้ ไม่ เปลี่ยนเส้นทางของเซิร์ฟเวอร์ที่จัดการโดย Crafty", + "การเปลี่ยนเส้นทาง สามารถ ทำให้สิ่งต่างๆ เสียหาย โดยเฉพาะบนระบบปฏิบัติการประเภท Linux ที่การอนุญาตของไฟล์ถูกจำกัดไว้มากกว่า", + "

", + "หากคุณรู้สึกว่าต้องเปลี่ยนตำแหน่งของเซิร์ฟเวอร์ คุณสามารถทำได้ตราบใดที่คุณให้สิทธิ์ผู้ใช้ \"crafty\" ในการอ่าน / เขียนไปยังเส้นทางเซิร์ฟเวอร์", + "
", + "
", + "บน Linux วิธีที่ดีที่สุดคือดำเนินการคำสั่งดังต่อไปนี้:
", + "", + " sudo chown crafty:crafty /path/to/your/server -R
", + " sudo chmod 2775 /path/to/your/server -R
", + "
" + ], + "title": "พื้นที่ตั้งค่าเซิร์ฟเวอร์" + }, + "serverDetails": { + "backup": "สำรองข้อมูล", + "config": "ตั้งค่า", + "files": "ไฟล์", + "filter": "กรองบันทึก", + "filterList": "ข้อความที่ถูกกรอง", + "logs": "บันทึก", + "metrics": "สถิติ", + "playerControls": "การจัดการผู้เล่น", + "reset": "รีเซ็ตการเลื่อน", + "schedule": "กำหนดการ", + "serverDetails": "รายละเอียดเซิร์ฟเวอร์", + "terminal": "เทอร์มินัล" + }, + "serverFiles": { + "clickUpload": "คลิกที่นี่เพื่อเลือกไฟล์ของคุณ", + "close": "ปิด", + "createDir": "สร้างโฟล์เดอร์ใหม่", + "createDirQuestion": "คุณอยากเรียกโฟล์เดอร์ใหม่นี้ว่าอะไร?", + "createFile": "สร้างไฟล์ใหม่", + "createFileQuestion": "คุณอยากเรียกไฟล์ใหม่นี้ว่าอะไร?", + "default": "ค่าเริ่มต้น", + "delete": "ลบ", + "deleteItemQuestion": "คุณแน่ใจหรือไม่ว่าต้องการลบ \" + name + \"?", + "deleteItemQuestionMessage": "คุณกำลังลบ \\\"\" + path + \"\\\"!

การกระทำนี้จะไม่สามารถย้อนกลับได้ และจะสูญหายไปตลอดกาล!", + "download": "ดาวน์โหลด", + "editingFile": "แก้ไขไฟล์", + "error": "เกิดข้อผิดพลาดขณะรับไฟล์", + "fileReadError": "ข้อผิดพลาดในการอ่านไฟล์", + "files": "ไฟล์", + "keybindings": "แป้นพิมพ์ลัด", + "loadingRecords": "กำลังโหลดไฟล์...", + "noDelete": "ไม่", + "noscript": "ตัวจัดการไฟล์จะไม่ทำงานหากไม่มี JavaScript", + "rename": "แก้ไขชื่อ", + "renameItemQuestion": "คุณจะตั้งชื่อใหม่ว่าอะไร?", + "save": "บันทึก", + "size": "สลับขนาดตัวแก้ไข", + "stayHere": "อย่าออกจากหน้านี้!", + "unsupportedLanguage": "คำเตือน: นี่ไม่ใช่ประเภทไฟล์ที่รองรับ", + "unzip": "แตกไฟล์", + "upload": "อัปโหลด", + "uploadTitle": "อัปโหลดไฟล์ไปที่: ", + "waitUpload": "โปรดรอสักครู่ในขณะที่เราอัปโหลดไฟล์ของคุณ... การกระทำนี้อาจใช้เวลาสักครู่", + "yesDelete": "ใช่ม ฉันเข้าใจผลที่ตามมา" + }, + "serverMetrics": { + "resetZoom": "รีเซ็ตการซูม", + "zoomHint1": "หากต้องการซูมกราฟ ให้กดปุ่ม Shift ค้างไว้แล้วใช้ลูกกลิ้งเมาส์", + "zoomHint2": "หรือกดปุ่ม Shift ค้างไว้ จากนั้นคลิกและลากบริเวณที่คุณต้องการซูมเข้า" + }, + "serverPlayerManagement": { + "bannedPlayers": "ผู้เล่นที่ถูกแบน", + "loadingBannedPlayers": "กำลังโหลดผู้เล่นที่ถูกแบน", + "players": "ผู้เล่น" + }, + "serverScheduleConfig": { + "backup": "สำรองข้อมูลเซิร์ฟเวอร์", + "basic": "ขั้นพื้นฐาน", + "children": "งานย่อยที่เชื่อมโยง: ", + "command": "คำสั่ง", + "command-explain": "คุณอยากให้เราดำเนินการคำสั่งใด? ไม่ต้องใส่ '/'", + "cron": "ครอน", + "cron-explain": "ป้อนครอนของคุณ -- หมายเหตุ: 0 = วันจันทร์ในตัวเลือกสุดท้าย", + "custom": "คำสั่งที่กำหนดเอง", + "days": "วัน", + "enabled": "เปิดใช้งาน", + "hours": "ชั่วโมง", + "interval": "ความถี่", + "interval-explain": "คุณต้องการดำเนินการกำหนดการนี้บ่อยแค่ไหน?", + "minutes": "นาที", + "offset": "การหน่วงเวลา", + "offset-explain": "เราควรรอนานแค่ไหนจึงจะเริ่มทำงานนี้หลังจากเริ่มภารกิจแรกแล้ว (วินาที)", + "one-time": "ลบหลังจากดำเนินการ", + "parent": "เลือกกำหนดการที่เป็นผู้ปกครอง", + "parent-explain": "กำหนดการใดควรเรียกใช้งานกำหนดการนี้", + "reaction": "ลูกโซ่", + "restart": "รีสตาร์ทเซิร์ฟเวอร์", + "select": "เลือกปฏิกิริยา ขั้นพื้นฐาน / ครอน / ลูกโซ่", + "start": "เริ่มเซิร์ฟเวอร์", + "stop": "ปิดเซิร์ฟเวอร์", + "time": "เวลา", + "time-explain": "คุณต้องการให้กำหนดการของคุณดำเนินการกี่โมง?" + }, + "serverSchedules": { + "action": "การกระทำ", + "areYouSure": "ลบงานที่กำหนดเวลาไว้?", + "cancel": "ยกเลิก", + "cannotSee": "ไม่เห็นอะไรเลยใช่ใหม?", + "cannotSeeOnMobile": "ลองคลิกงานที่กำหนดเวลาไว้เพื่อดูรายละเอียดทั้งหมด", + "child": "ลูกของกำหนดการที่พร้อม ID ", + "close": "ปิด", + "command": "คำสั่ง", + "confirm": "ยืนยัน", + "confirmDelete": "คุณต้องการลบงานที่กำหนดเวลาไว้นี้หรือไม่ สิ่งนี้ไม่สามารถยกเลิกได้.", + "create": "สร้างกำหนดการใหม่", + "cron": "ครอนสตริง", + "delete": "ลบ", + "details": "รายละเอียดกำหนดการ", + "edit": "แก้ไข", + "enabled": "เปิดใช้งาน", + "every": "ทั้งหมด", + "interval": "ช่วงเวลา", + "name": "ชื่อ", + "newSchedule": "สร้างกำหนดการใหม่", + "nextRun": "ทำงานครั้งต่อไป", + "no": "ไม่", + "no-schedule": "ขณะนี้ไม่มีกำหนดการสำหรับเซิร์ฟเวอร์นี้ หากต้องการเริ่มต้น คลิก", + "scheduledTasks": "งานที่กำหนดเวลาไว้", + "yes": "ใช่" + }, + "serverStats": { + "cpuUsage": "การใช้งานซีพียู", + "description": "คำอธิบาย", + "errorCalculatingUptime": "เกิดข้อผิดพลาดในการคำนวณสถานะการออนไลน์", + "memUsage": "การใช้งานหน่วยความจำ", + "offline": "ออฟไลน์", + "online": "ออนไลน์", + "players": "ผู้เล่น", + "serverStarted": "เวลาเริ่มการทำงานเซิร์ฟเวอร์", + "serverStatus": "สถานะเซิร์ฟเวอร์", + "serverTime": "UTC Time", + "serverTimeZone": "โซนเวลาของเซิร์ฟเวอร์", + "serverUptime": "เวลาทำงานของเซิร์ฟเวอร์", + "starting": "หน่วงเวลาเริ่มต้น", + "unableToConnect": "ไม่สามารถเชื่อมต่อ", + "version": "เวอร์ชั่น" + }, + "serverTerm": { + "commandInput": "ป้อนคำสั่งของคุณ", + "delay-explained": "บริการ/ตัวแทนเพิ่งเริ่มต้นและกำลังชะลอการเริ่มต้นเซิร์ฟเวอร์ Minecraft", + "importing": "กำลังนำเข้า...", + "installing": "กำลังติดตั้ง...", + "restart": "รีสตาร์ท", + "sendCommand": "ส่งคำสั่ง", + "start": "เริ่มต้น", + "starting": "ชะลอการเริ่มต้น", + "stop": "หยุด", + "stopScroll": "หยุดการเลื่อนอัตโนมัติ", + "updating": "กำลังอัปเดต..." + }, + "serverWizard": { + "absoluteServerPath": "เส้นทางที่แน่นอนไปยังเซิร์ฟเวอร์ของคุณ", + "absoluteZipPath": "เส้นทางที่แน่นอนไปยังเซิร์ฟเวอร์ของคุณ", + "addRole": "เพิ่มเซิร์ฟเวอร์ให้กับบทบาทที่มีอยู่", + "autoCreate": "หากไม่มีใครถูกเลือก Crafty จะสร้างให้!", + "bePatient": "โปรดอดทนรอในขณะที่เรา ' + (นำเข้า ? 'importing' : 'download') + ' เซิร์ฟเวอร์", + "buildServer": "สร้างเซิร์ฟเวอร์!", + "clickRoot": "คลิกที่นี่เพื่อเลือกไดเรกทอรีหลัก", + "close": "ปิด", + "defaultPort": "ค่าเริ่มต้น 25565", + "downloading": "กำลังดาวน์โหลดเซิร์ฟเวอร์...", + "explainRoot": "โปรดคลิกที่ปุ่มด้านล่างเพื่อเลือกไดเรกทอรีหลักของเซิร์ฟเวอร์ของคุณภายในแหล่งข้อมูล (archive)", + "importServer": "นำเข้าเซิร์ฟเวอร์ที่มีอยู่แล้ว", + "importServerButton": "นำเข้าเซิร์ฟเวอร์!", + "importZip": "นำเข้าจากไฟล์ซิป", + "importing": "กำลังนำเข้าเซิร์ฟเวอร์...", + "labelZipFile": "เลือกไฟล์ซิปของคุณ", + "maxMem": "หน่วยความจำสูงสุด", + "minMem": "หน่วยความจำขั้นต่ำ", + "myNewServer": "เซิร์ฟเวอร์ใหม่ของฉัน", + "newServer": "สร้างเซิร์ฟเวอร์ใหม่", + "quickSettings": "การตั้งค่าด่วน", + "quickSettingsDescription": "ไม่ต้องกังวล คุณสามารถเปลี่ยนแปลงสิ่งเหล่านี้ได้ในภายหลัง", + "resetForm": "รีเซ็ตแบบฟอร์ม", + "save": "บันทึก", + "selectRole": "เลือกบทบาท", + "selectRoot": "เลือกไดเรกทอรีหลัก", + "selectServer": "เลือกเซิร์ฟเวอร์", + "selectType": "ประเภทเซิร์ฟเวอร์ (วานิลลา, เซิร์ฟเวอร์, ม็อด, ฯลฯ)", + "selectVersion": "เลือกเวอร์ชั่น", + "selectZipDir": "เลือกไดเร็กทอรีในแหล่งข้อมูลที่คุณต้องการให้เราแตกไฟล์", + "serverJar": "แฟ้มกระทำการของเซิร์ฟเวอร์ (.jar)", + "serverName": "ชื่อเซิร์ฟเวอร์", + "serverPath": "เส้นทางเซิร์ฟเวอร์", + "serverPort": "พอร์ตเซิร์ฟเวอร์", + "serverSelect": "เลือกเซิร์ฟเวอร์", + "serverType": "ประเภทเซิร์ฟเวอร์", + "serverUpload": "อัปโหลดเซิร์ฟเวอร์ซิป", + "serverVersion": "เวอร์ชันเซิร์ฟเวอร์", + "sizeInGB": "ขนาดเป็นกิกะไบต์", + "uploadButton": "อัปโหลด", + "uploadZip": "อัปโหลดไฟล์ซิปสำหรับการนำเข้าเซิร์ฟเวอร์", + "zipPath": "เส้นทางเซิร์ฟเวอร์" + }, + "sidebar": { + "contribute": "สนับสนุนเรา", + "credits": "เครดิต", + "dashboard": "แผงควบคุม", + "documentation": "เอกสารประกอบ", + "inApp": "เอกสารประกอบภายในแอป", + "navigation": "เมนูนำทาง", + "newServer": "สร้างเซิร์ฟเวอร์ใหม่", + "servers": "เซิร์ฟเวอร์" + }, + "startup": { + "almost": "เสร็จสิ้นการทำงาน. รอซักครู่...", + "internals": "กำหนดค่าและเริ่มการทำงานภายในของ Crafty", + "internet": "กำลังตรวจสอบการเชื่อมต่ออินเทอร์เน็ต", + "server": "กำลังเริ่มต้นการทำงาน ", + "serverInit": "กำลังเริ่มต้นการทำงานเซิร์ฟเวอร์", + "starting": "Crafty กำลังเริ่มการทำงาน...", + "tasks": "กำลังเริ่มการทำงานกำหนดการ" + }, + "userConfig": { + "apiKey": "คีย์ API", + "auth": "ให้สิทธิ์การเข้าถึง?", + "config": "ตั้งค่า", + "configArea": "พื้นที่ตั้งค่าผู้ใช้", + "configAreaDesc": "ที่นี่คือที่ที่คุณเปลี่ยนการตั้งค่าผู้ใช้ทั้งหมดของคุณ", + "confirmDelete": "คุณแน่ใจหรือไม่ว่าต้องการลบผู้ใช้รายนี้ การกระทำนี้ไม่สามารถย้อนกลับได้", + "craftyPermDesc": "สิทธิ์เข้าถึง Crafty ที่ผู้ใช้คนนี้มี ", + "craftyPerms": "สิทธิ์เข้าถึง Crafty: ", + "created": "สร้างเมื่อ: ", + "delSuper": "คุณไม่สามารถลบผู้ใช้ขั้นสูงได้", + "deleteUser": "ลบผู้ใช้: ", + "deleteUserB": "ลบผู้ใช้", + "enabled": "เปิดใช้งาน", + "gravDesc": "อีเมลนี้มีไว้สำหรับใช้กับ Gravatar™ เท่านั้น Crafty จะไม่ใช้อีเมลนี้เพื่อสิ่งอื่นใดนอกจากการค้นหา Gravatar™ ของคุณไม่ว่าในกรณีใดก็ตาม", + "gravEmail": "อีเมล Gravatar™", + "lastIP": "IP ล่าสุด: ", + "lastLogin": "เข้าสู่ระบบครั้งล่าสุด: ", + "lastUpdate": "การปรับปรุงครั้งล่าสุด: ", + "leaveBlank": "หากต้องการแก้ไขผู้ใช้โดยไม่เปลี่ยนรหัสผ่านให้เว้นว่างไว้", + "manager": "ผู้จัดการ", + "member": "สมาชิก?", + "notExist": "คุณไม่สามารถลบสิ่งที่ไม่มีอยู่ได้!", + "pageTitle": "แก้ไขผู้ใช้", + "pageTitleNew": "สร้างผู้ใช้", + "password": "รหัสผ่านใหม่", + "permName": "ชื่อการอนุญาต", + "repeat": "ยืนยันรหัสผ่าน", + "roleName": "ชื่อบทบาท", + "selectManager": "เลือกผู้จัดการสำหรับผู้ใช้นี้", + "super": "ผู้ใช้ขั้นสูง", + "userLang": "ภาษาของผู้ใช้", + "userName": "ชื่อผู้ใช้", + "userNameDesc": "คุณต้องการเรียกผู้ใช้รายนี้ว่าอะไร?", + "userRoles": "บทบาทของผู้ใช้", + "userRolesDesc": "บทบาทที่ผู้ใช้รายนี้เป็นสมาชิก", + "userSettings": "การตั้งค่าผู้ใช้", + "userTheme": "ธีม UI", + "uses": "จำนวนการใช้งานที่อนุญาต (-1==ไม่มีขีดจำกัด)" + }, + "webhooks": { + "areYouSureDel": "คุณแน่ใจหรือไม่ว่าต้องการลบ Webhook นี้?", + "areYouSureRun": "คุณแน่ใจหรือไม่ว่าต้องการทดสอบ Webhook นี้?", + "backup_server": "การสำรองข้อมูลเซิร์ฟเวอร์เสร็จสมบูรณ์", + "bot_name": "ชื่อบอท", + "color": "เลือกการเน้นสี", + "crash_detected": "เซิร์ฟเวอร์ขัดข้อง", + "edit": "แก้ไข", + "enabled": "เปิดใช้งาน", + "jar_update": "อัปเดตแฟ้มกระทำการเซิร์ฟเวอร์แล้ว", + "kill": "เซิร์ฟเวอร์ถูกบังคับหยุด", + "name": "ชื่อ", + "new": "สร้าง Webhook ใหม่", + "newWebhook": "สร้าง Webhook ใหม่", + "no-webhook": "ขณะนี้ไม่มี webhooks สำหรับเซิร์ฟเวอร์นี้ หากต้องการเริ่มต้น คลิก", + "run": "ทดสอบเรียกใช้ Webhook", + "send_command": "ได้รับคำสั่งเซิร์ฟเวอร์แล้ว", + "start_server": "เซิร์ฟเวอร์เริ่มต้นแล้ว", + "stop_server": "เซิร์ฟเวอร์หยุดทำงาน", + "trigger": "สิ่งกระตุ้น", + "type": "ประเภท Webhook", + "url": "URL ของ Webhook", + "webhook_body": "ภายใน Webhook", + "webhooks": "Webhooks" + } +} diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json new file mode 100644 index 00000000..1ab75a0d --- /dev/null +++ b/app/translations/tr_TR.json @@ -0,0 +1,668 @@ +{ + "404": { + "contact": "Crafty Control Destek Discord Sunucusu", + "notFound": "Sayfa Bulunamadı", + "unableToFind": "Aradığınız sayfayı bulamıyoruz. Lütfen tekrar deneyin, veya geri gidip sayfayı yenileyin." + }, + "accessDenied": { + "accessDenied": "Erişim Reddedildi", + "contact": "Crafty Control Destek Discord Sunucusu", + "contactAdmin": "Bu içeriğe erişebilmek için sunucu yöneticinizle iletişim kurun, ya da bu içeriğe erişmeniz gerektiğini düşünüyorsanız, destek ile iletişime geçin.", + "noAccess": "Bu kaynağa erişiminiz yok." + }, + "apiKeys": { + "apiKeys": "API Anahtarları", + "auth": "Yetkili mi? ", + "buttons": "İşlemler", + "config": "Konfigürasyon", + "crafty": "Crafty: ", + "createNew": "Yeni API tokeni oluştur", + "created": "Oluşturuldu", + "deleteKeyConfirmation": "Bu API anahtarını silmek istediğine emin misin? Bu geri alınamaz.", + "deleteKeyConfirmationTitle": "${keyId} API anahtarını kaldırma işlemi.", + "getToken": "Bir Token Al", + "name": "Ad", + "nameDesc": "Bu API tokeninin adı ne olsun?", + "no": "Hayır", + "pageTitle": "Kullanıcı API Anahtarlarını Düzenle", + "permName": "Yetki İsmi", + "perms": "Yetkiler", + "server": "Sunucu: ", + "superUser": "Süper Kullanıcı", + "yes": "Evet" + }, + "base": { + "doesNotWorkWithoutJavascript": "Uyarı: Crafty, Javascript aktifleştirilmediği zaman düzgün çalışmaz!" + }, + "credits": { + "developmentTeam": "Geliştirme Takımı", + "hugeDesc": " ", + "pageDescription": "Bu kişiler olmadan, Crafty olmazdı.", + "pageTitle": "Katkıda Bulunanlar", + "patreonDesc": "Patreon / Ko-fi destekçilerimize kocaman bir TEŞEKKÜR!", + "patreonOther": "Diğer", + "patreonSupporter": "Patreon / Ko-fi Destekçileri", + "patreonUpdate": "Son güncelleme:", + "retiredStaff": "Emekli Personeller", + "subscriberName": "İsim", + "subscriptionLevel": "Seviye", + "supportTeam": "Destek ve Dokümantasyon", + "thankYou": " ", + "translationDesc": "Çeviri yapan topluluğumuza kocaman bir TEŞEKKÜR! [ Aktif = 🟢 İnaktif/Emekli = ⚪ ]", + "translationName": "İsim", + "translationTitle": "Çeviri", + "translator": "Çevirmenler" + }, + "customLogin": { + "apply": "Uygula", + "backgroundUpload": "Arkaplan Yükleme", + "customLoginPage": "Giriş Ekranını Düzenle", + "delete": "Sil", + "labelLoginImage": "Oturum Açma Sayfası Arkaplanını Seç", + "loginBackground": "Oturum Açma Sayfası", + "loginImage": "Oturum açma sayfası için bir arka plan resmi yükleyin.", + "loginOpacity": "Oturum Açma Penceresi Opaklığını Seçin", + "pageTitle": "Özelleştirilmiş Oturum Açma Sayfası", + "preview": "Ön İzleme", + "select": "Seç", + "selectImage": "Bir resim seçin" + }, + "dashboard": { + "actions": "İşlemler", + "allServers": "Tüm Sunucular", + "avg": "Ort", + "backups": "Yedeklemeler", + "bePatientClone": "Sunucuyu klonlarken lütfen sabırlı olunuz.
Bu ekran birazdan kendini yenileyecektir", + "bePatientRestart": "Sunucuyu yeniden başlatırken lütfen sabırlı olunuz.
Bu ekran birazdan kendini yenileyecektir", + "bePatientStart": "Sunucuyu başlatırken başlatırken lütfen sabırlı olunuz.
Bu ekran birazdan kendini yenileyecektir", + "bePatientStop": "Sunucuyu durdururken başlatırken lütfen sabırlı olunuz.
Bu ekran birazdan kendini yenileyecektir", + "cannotSee": "Gözükmeyen şeyler mi var?", + "cannotSeeOnMobile": "Mobilde gözükmeyen şeyler mi var?", + "cannotSeeOnMobile2": "Tabloyu yana doğru kaydırmayı deneyin.", + "clone": "Klonla", + "cloneConfirm": "Bu sunucuyu klonlamak istediğinizden emin misiniz? Bu işlem biraz zaman alabilir.", + "cpuCores": "CPU Çekirdekler", + "cpuCurFreq": "CPU Mevcut Hızı", + "cpuMaxFreq": "CPU Maksimum Hızı", + "cpuUsage": "CPU Kullanımı", + "crashed": "Çöktü", + "dashboard": "Arayüz", + "delay-explained": "Servis/ajan yakın zaman içerisinde başlatıldı ve minecraft sunucu örneğinin başlamasını erteliyor", + "host": "Ana Makine", + "installing": "İndiriliyor...", + "kill": "İşlemi Sonlandır", + "killing": "İşlem sonlandırılıyor...", + "lastBackup": "En Son:", + "max": "Maks", + "memUsage": "Bellek Kullanımı", + "motd": "MOTD", + "newServer": "Yeni Sunucu Oluştur", + "nextBackup": "Sonraki:", + "no-servers": "Şu anda sunucu yok. Başlamak için,", + "offline": "Çevrimdışı", + "online": "Çevrimiçi", + "players": "Oyuncular", + "restart": "Yeniden Başlat", + "sendingCommand": "Komutun gönderiliyor", + "server": "Sunucu", + "servers": "Sunucular", + "size": "Sunucu Dir Boyutu", + "start": "Başlat", + "starting": "Gecikmeli Başlangıç", + "status": "Durum", + "stop": "Dur", + "storage": "Saklama Alanı", + "version": "Sürüm", + "welcome": "Crafty Controller'a Hoşgeldiniz!" + }, + "datatables": { + "i18n": { + "aria": { + "sortAscending": ": artan sütun sıralamasını aktifleştir", + "sortDescending": ": azalan sütun sıralamasını aktifleştir" + }, + "buttons": { + "collection": "Koleksiyon ", + "colvis": "Sütun Görünürlüğü", + "colvisRestore": "Görünürlüğü eski haline getir", + "copy": "Kopyala", + "copyKeys": "Tablodaki veriyi panoya kopyalamak için CTRL veya u2318 + C tuşlarına basınız.

İptal etmek için bu mesaja tıklayın veya esc tuşuna basın.", + "copySuccess": { + "1": "Panoya 1 satır kopyalandı", + "_": "Panoya %d satır kopyalandı" + }, + "copyTitle": "Panoya Kopyala", + "csv": "CSV", + "excel": "Excel", + "pageLength": { + "-1": "Bütün satırları göster", + "1": "1 satır göster", + "_": "%d satır göster" + }, + "pdf": "PDF", + "print": "Yazdır" + }, + "decimal": "", + "emptyTable": "Tabloda veri bulunmuyor", + "info": "_TOTAL_ kayıttan _START_ - _END_ arasındaki kayıtlar gösteriliyor", + "infoEmpty": "0 kayıttan 0 - 0 arasındaki kayıtlar gösteriliyor", + "infoFiltered": "(_MAX_ kayıt içerisinden filtrelenen)", + "infoPostFix": "", + "lengthMenu": "_MENU_ kayıt göster", + "loadingRecords": "Yükleniyor...", + "paginate": { + "first": "İlk", + "last": "Son", + "next": "Sonraki", + "previous": "Önceki" + }, + "processing": "İşleniyor...", + "search": "Ara:", + "select": { + "cells": { + "0": "Seçmek için bir hücreye tıklayın", + "1": "%d hücre seçildi", + "_": "%d hücre seçildi" + }, + "columns": { + "0": "Seçmek için bir sütuna tıklayın", + "1": "%d sütun seçildi", + "_": "%d sütun seçildi" + }, + "rows": { + "0": "Seçmek için bir satıra tıklayın", + "1": "%d satır seçildi", + "_": "%d satır seçildi" + } + }, + "thousands": ".", + "zeroRecords": "Eşleşen kayıt bulunamadı" + } + }, + "error": { + "agree": "Kabul Et", + "bedrockError": "Bedrock indirmeleri kullanılamıyor. Lütfen kontrol edin", + "cancel": "İptal", + "contact": "Crafty Control Destek Discord Sunucusu", + "craftyStatus": "Crafty'nin durum sayfası", + "cronFormat": "Geçersiz Cron biçimi algılandı", + "embarassing": "Hay aksi, bu çok utanç verici.", + "error": "Hata!", + "eulaAgree": "Kabul ediyor musun?", + "eulaMsg": "Minecraft EULA'yı kabul etmelisiniz. ", + "eulaTitle": "EULA'yı Kabul Et", + "fileError": "Dosya türü bir resim olmalıdır.", + "fileTooLarge": "Yükleme başarısız oldu. Dosya yüklemesi çok büyük. Yardım için sistem yöneticisine başvurun.", + "hereIsTheError": "Hata burada", + "installerJava": "{} indirilemedi : Forge sunucu yüklemeleri Java gerektirir. Java'nın yüklü olmadığını tespit ettik. Lütfen Java'yı yükleyin ve ardından sunucuyu yükleyin.", + "internet": "Crafty'yi çalıştıran makinenin internet bağlantısı olmadığını tespit ettik. Sunucuya istemci bağlantıları sınırlı olabilir.", + "migration": "Crafty'nin ana sunucu veri deposu yeni bir yere taşınıyor. Bu süre zarfında tüm sunucu başlangıçları askıya alınmıştır. Lütfen biz bu taşıma işlemini tamamlarken bekleyin", + "no-file": "İstenen dosyayı bulamıyoruz. Dosya yolunu tekrar kontrol edin. Crafty'nin doğru izinleri var mı?", + "noInternet": "Crafty internete erişimde sorun yaşıyor. Sunucu oluşturma devre dışı bırakıldı. Lütfen internet bağlantınızı kontrol edin ve bu sayfayı yenileyin.", + "noJava": "{} sunucusu başlamatılamadı. Hata kodu: Java'nın yüklü olmadığını tespit ettik. Lütfen Java'yı yükleyin ve ardından sunucuyu başlatın.", + "not-downloaded": "Çalıştırılabilir dosyanızı bulamıyoruz. İndirme işlemi tamamlandı mı? İzinler çalıştırılabilir olarak ayarlandı mı?", + "portReminder": "{} ilk kez çalıştırılıyor olduğunu tespit ettik. Bunu internetten uzaktan erişilebilir kılmak için {} bağlantı noktasını yönlendiriciniz/güvenlik duvarınız üzerinden ilettiğinizden emin olun.", + "privMsg": "ve ", + "serverJars1": "Sunucu JARs API'ına erişilemiyor.", + "serverJars2": "en güncel bilgilere sahiptir", + "start-error": "{} sunucusu başlamatılamadı. Hata kodu: {}", + "superError": "Bu işlemi tamamlamak için süper kullanıcı olmanız gerekir.", + "terribleFailure": "Ne Korkunç Bir Hata!" + }, + "footer": { + "allRightsReserved": "Tüm hakları saklıdır", + "copyright": "Telif Hakkı", + "version": "Sürüm" + }, + "login": { + "forgotPassword": "Şifremi Unuttum", + "login": "Oturum Aç", + "password": "Şifre", + "username": "Kullanıcı Adı", + "viewStatus": "Herkese Açık Durum Sayfasını Görüntüle" + }, + "notify": { + "activityLog": "Faaliyet Günlükleri", + "backupComplete": "{} sunucusu için yedekleme başarıyla tamamlandı", + "backupStarted": "{} sunucusu için yedekleme başlatıldı", + "downloadLogs": "Destek Günlükleri İndirilsin mi?", + "finishedPreparing": "Destek günlüklerinizi hazırlamayı tamamladık. İndirmek için lütfen indir'e tıklayın", + "logout": "Oturumu Kapat", + "preparingLogs": " Günlüklerinizi hazırlarken lütfen bekleyin... Hazır olduklarında bir bildirim göndereceğiz. Bu, büyük dağıtımlar için biraz zaman alabilir.", + "supportLogs": "Destek Günlükleri" + }, + "offline": { + "offline": "Çevrimdışı", + "pleaseConnect": "Crafty'yi kullanmak için lütfen internete bağlanın." + }, + "panelConfig": { + "adminControls": "Yönetici Kontrolleri", + "allowedServers": "İzin Verilen Sunucular", + "apply": "Uygula", + "assignedRoles": "Atanan Roller", + "cancel": "İptal", + "clearComms": "Çalıştırılmamış Komutları Temizle", + "custom": "Crafty'yi Özelleştir", + "delete": "Sil", + "edit": "Düzenle", + "enableLang": "Tüm Dilleri Etkinleştir", + "enabled": "Etkin", + "globalExplain": "Crafty'nin tüm sunucu dosyalarınızı depoladığı yer. (Yolu ile /servers/[uuid of server] ekleyeceğiz.)", + "globalServer": "Genel Sunucular Rehberi", + "json": "Config.json", + "match": "Şifreler eşleşmelidir", + "newRole": "Yeni Rol Ekle", + "newUser": "Yeni Kullanıcı Ekle", + "noMounts": "Arayüzde montaj gösterme", + "pageTitle": "Panel Konfigürasyonu", + "role": "Rol", + "roleUsers": "Role Sahip Kullanıcılar", + "roles": "Roller", + "save": "Kaydet", + "select": "Seç", + "superConfirm": "Yalnızca bu kullanıcının HER ŞEYE (tüm kullanıcı hesapları, sunucular, panel ayarları vb.) erişmesini istiyorsanız devam edin. Süper kullanıcı haklarınızı bile kaldırabilirler.", + "superConfirmTitle": "Süper kullanıcıyı etkinleştirmek istediğinize emin misiniz?", + "title": "Crafty Konfigürasyon", + "user": "Kullanıcı", + "users": "Kullanıcılar" + }, + "rolesConfig": { + "config": "Rol Konfigürasyonu", + "configDesc": "Rolünüzün konfigürasyonu buradan değiştirebilirsiniz", + "configUpdate": "Son Güncelleme: ", + "created": "Oluşturulma: ", + "delRole": "Rolü Sil", + "doesNotExist": "Henüz var olmayan bir şeyi silemezsiniz", + "pageTitle": "Rolü Düzenle", + "pageTitleNew": "Yeni Rol", + "permAccess": "İzin?", + "permName": "İzin Adı", + "permsServer": "Bu rolün belirtilen sunucular için sahip olduğu izinler", + "roleConfigArea": "Rol Konfigürasyon Alanı", + "roleDesc": "Bu rolü nasıl adlandırmak istersiniz?", + "roleName": "Rol Adı: ", + "rolePerms": "Rol İzinleri", + "roleServers": "İzin Verilen Sunucular", + "roleTitle": "Rol Ayarları", + "roleUserName": "Kullanıcı Adı", + "roleUsers": "Role Sahip Kullanıcılar: ", + "selectManager": "Bu rol için bir yönetici seçin", + "serverAccess": "Erişim?", + "serverName": "Sunucu Adı", + "serversDesc": "bu rolün erişmesine izin verilen sunucular" + }, + "serverBackups": { + "after": "Yedeklemeden sonra bir komut çalıştır", + "backupAtMidnight": "Gece yarısında otomatik yedekleme yapılsın mı?", + "backupNow": "Backup Now!", + "backupTask": "Bir yedekleme görevi başlatıldı.", + "before": "Yedeklemeden önce bir komut çalıştır", + "cancel": "İptal", + "clickExclude": "İstisnaları seçmek için tıklayın", + "compress": "Yedeklemeyi Sıkıştır", + "confirm": "Onayla", + "confirmDelete": "Bu yedeği silmek istediğine emin misin? Bu geri alınamaz.", + "confirmRestore": "Bu yedeği geri yüklemek istediğinizden emin misiniz? Tüm mevcut sunucu dosyaları yedeklemedeki durumuna dönecek ve kurtarılamayacaktır.", + "currentBackups": "Mevcut Yedekmeler", + "delete": "Sil", + "destroyBackup": "\" + file_to_del + \" yedeklemesi yok edilsin mi?", + "download": "İndir", + "excludedBackups": "Hariç Tutulan Yollar: ", + "excludedChoose": "Yedeklemelerinizden hariç tutmak istediğiniz yolları seçin", + "exclusionsTitle": "Yedekleme İstisnaları", + "maxBackups": "Maksimum Yedekleme Sayısı", + "maxBackupsDesc": "Crafty N yedeklemeden fazlasını saklamayacak, en eskisini silecektir (tümünü saklamak için 0 girin)", + "options": "Seçenekler", + "path": "Dosya Yolu", + "restore": "Geri Yükleme", + "restoring": "Yedekleme geri yükleniyor. Bu biraz zaman alabilir. Lütfen sabırlı olun.", + "save": "Kaydet", + "shutdown": "Yedekleme süresince sunucuyu kapat", + "size": "Boyut", + "storageLocation": "Depolama Konumu", + "storageLocationDesc": "Yedekmeleri nerede saklamak istiyorsunuz?" + }, + "serverConfig": { + "bePatientDelete": "Sunucunuzu Crafty panelinden kaldırırken lütfen sabırlı olun. Bu ekran birazdan kapanacaktır.", + "bePatientDeleteFiles": "Sunucunuzu Crafty panelinden kaldırırken ve dosyalarını silerken lütfen sabırlı olun. Bu ekran birazdan kapanacaktır.", + "bePatientUpdate": "Sunucuyu güncellerken lütfen sabırlı olun. İndirme süreleri internet hızınıza bağlı olarak değişebilir.
Bu ekran birazdan kendini yenileyecektir", + "cancel": "İptal", + "crashTime": "Çökme Zaman Aşımı", + "crashTimeDesc": "Sunucunuzun çöktüğünü varsaymadan önce ne kadar beklemeliyiz?", + "deleteFilesQuestion": "Sunucu dosyaları makineden silinsin mi?", + "deleteFilesQuestionMessage": "Crafty'nin ana makineden tüm sunucu dosyalarını silmesini ister misiniz?

Buna sunucu yedeklemeleri de dahildir.", + "deleteServer": "Sunucuyu Sil", + "deleteServerQuestion": "Sunucu silinsin mi?", + "deleteServerQuestionMessage": "Bu sunucuyu silmek istediğinizden emin misiniz? Bundan sonra geri dönüş yok...", + "exeUpdateURL": "Sunucu Çalıştırılabilir Güncelleme URL'si", + "exeUpdateURLDesc": "Güncellemeler için Doğrudan İndirme URL'si.", + "ignoredExits": "Yok Sayılan Çökme Çıkış Kodları", + "ignoredExitsExplain": "Crafty'nin Crash algılamasının normal bir 'durdurma' olarak görmezden gelmesi gereken çıkış kodları (virgülle ayrılmış)", + "javaNoChange": "Geçersiz Kılma", + "javaVersion": "Geçerli Java sürümünü geçersiz kıl", + "javaVersionDesc": "Java'yı geçersiz kılacaksanız, 'çalıştırma komutu' içindeki geçerli Java yolunuzun tırnak içine alındığından emin olun (varsayılan 'java' değişkeni hariç)", + "noDelete": "Hayır, geri dön", + "noDeleteFiles": "Hayır, sadece panelden kaldırın", + "removeOldLogsAfter": "Eski Günlükleri Kaldırma Süresi", + "removeOldLogsAfterDesc": "Bir günlük dosyasının silinmesi için kaç gün geçmesi gerekir (0 kapalıdır)", + "save": "Kaydet", + "sendingDelete": "Sunucu Siliniyor", + "sendingRequest": "İsteğiniz gönderiliyor...", + "serverAutoStart": "Sunucuyu Otomatik Başlatma", + "serverAutostartDelay": "Sunucuyu Otomatik Başlatma Gecikmesi", + "serverAutostartDelayDesc": "Otomatik başlatmadan önceki gecikme (Aşağıda etkinleştirilmişse)", + "serverCrashDetection": "Sunucu Çökmesi Algılama", + "serverExecutable": "Sunucu Çalıştırılabilir Dosyası", + "serverExecutableDesc": "Sunucunun çalıştırılabilir dosyası", + "serverExecutionCommand": "Sunucu Çalıştırma Komutu", + "serverExecutionCommandDesc": "Gizli bir terminalde başlatılacaklar", + "serverIP": "Sunucu IP'si", + "serverIPDesc": "Crafty'nin istatistikler için bağlanması gereken IP (Sorun yaşarsanız 127.0.0.1 yerine gerçek bir ip deneyin)", + "serverLogLocation": "Sunucu Günlük Konumu", + "serverLogLocationDesc": "Günlük dosyasının konumu", + "serverName": "Sunucu Adı", + "serverNameDesc": "Sunucuya vermek istediğiniz ad", + "serverPath": "Sunucu Çalışma Dizini", + "serverPathDesc": "Mutlak tam yol (çalıştırılabilir dahil değil)", + "serverPort": "Sunucu Bağlantı Noktası (Portu)", + "serverPortDesc": "Crafty'nin istatistikler için bağlanması gereken bağlantı noktası (portu)", + "serverStopCommand": "Sunucu Durdurma Komutu", + "serverStopCommandDesc": "Programı durdurmak için gönderilecek komut", + "showStatus": "Herkese Açık Durum Sayfasında Göster", + "shutdownTimeout": "Kapanma Zaman Aşımı", + "statsHint1": "Sunucunuzun çalıştığı port buraya girilmelidir. Crafty sunucunuzun istatistiklerine böyle erişiyor.", + "statsHint2": "Bu, sunucunuzun portunu değiştirmez. Sunucu konfigürasyon dosyanızdaki portu da ayrıca değiştirmeniz gerekir.", + "stopBeforeDeleting": "Lütfen sunucuyu silmeden önce durdurun", + "timeoutExplain1": "Crafty'nin", + "timeoutExplain2": "komutunu çalıştırdıktan sonra sunucuyu kapatmaya zorlamadan önce sunucunuzun kapanmasını ne kadar bekleyeceği.", + "update": "Çalıştırılabilir Dosyayı Güncelle", + "yesDelete": "Evet, sil", + "yesDeleteFiles": "Evet, dosyaları sil" + }, + "serverConfigHelp": { + "desc": "Sunucunuzun konfigürasyonu buradan değiştirebilirsiniz", + "perms": [ + "Crafty tarafından yönetilen bir sunucunun konumlarının DEĞİŞTİRİLMEMESİ önerilir.", + "Konumları değiştirmek, özellikle dosya izinlerinin daha kilitli olduğu Linux tipi işletim sistemlerinde işleri BOZABİLİR.", + "

", + "Bir sunucunun bulunduğu yeri değiştirmek zorunda olduğunuzu düşünüyorsanız, \"crafty\" kullanıcısına sunucu yolunu okuma / yazma izni verdiğiniz sürece bunu yapabilirsiniz.", + "
", + "
", + "Linux'ta bu en iyi şekilde aşağıdakileri uygulayarak yapılır:
", + "", + " sudo chown crafty:crafty /sunucunuzun/konumu/ -R
", + " sudo chmod 2775 /sunucunuzun/konumu/ -R
", + "
" + ], + "title": "Sunucu Konfigürasyon Alanı" + }, + "serverDetails": { + "backup": "Yedekleme", + "config": "Konfigürasyon", + "files": "Dosyalar", + "filter": "Günlükleri Filtrele", + "filterList": "Filtrelenmiş Kelimeler", + "logs": "Günlükler", + "metrics": "Metrikler", + "playerControls": "Oyuncu Yönetimi", + "reset": "Kaydırmayı Sıfırla", + "schedule": "Zamanlama", + "serverDetails": "Sunucu Detayları", + "terminal": "Terminal" + }, + "serverFiles": { + "clickUpload": "Dosyalarınızı seçmek için buraya tıklayın", + "close": "Kapat", + "createDir": "Dizin oluştur", + "createDirQuestion": "Yeni dizinin adı ne olsun?", + "createFile": "Dosya oluştur", + "createFileQuestion": "Yeni dosyanın adı ne olsun?", + "default": "Varsayılan", + "delete": "Sil", + "deleteItemQuestion": "\" + name + \" klasör/dosyasını silmek istediğinizden emin misiniz?", + "deleteItemQuestionMessage": "\\\"\" + path + \"\\\" silenecektir!

Bu eylemin geri dönüşü olmayacak ve sonsuza kadar kaybolacak!", + "download": "İndir", + "editingFile": "Düzenlenen dosya:", + "error": "Dosyalar alınırken hata oluştu", + "fileReadError": "Dosya okuma hatası", + "files": "Dosyalar", + "keybindings": "Tuş Atamaları", + "loadingRecords": "Dosyalar yükleniyor...", + "noDelete": "Hayır", + "noscript": "Dosya yöneticisi JavaScript olmadan çalışmıyor", + "rename": "Yeniden Adlandır", + "renameItemQuestion": "Dosyanın yeni adı ne olsun?", + "save": "Kaydet", + "size": "Düzenleyici Boyutunu Değiştir", + "stayHere": "BU SAYFADAN AYRILMAYIN!", + "unsupportedLanguage": "Uyarı: Bu desteklenen bir dosya türü değil", + "unzip": "Fermuarı aç", + "upload": "Dosya Yükle", + "uploadTitle": "Dosyayı buraya yükle: ", + "waitUpload": "Lütfen dosyalarınızı yüklerken bekleyiniz... Bu biraz zaman alabilir.", + "yesDelete": "Evet, sonuçlarını anlıyorum" + }, + "serverMetrics": { + "resetZoom": "Yakınlaştırmayı Sıfırla", + "zoomHint1": "Grafiği yakınlaştırmak için shift tuşunu basılı tutun ve ardından kaydırma tekerleğini kullanın.", + "zoomHint2": "Ya da shift tuşunu basılı tutup yakınlaştırmak istediğiniz alana tıklayın ve sürükleyin." + }, + "serverPlayerManagement": { + "bannedPlayers": "Yasaklanmış Oyuncular", + "loadingBannedPlayers": "Yasaklanmış Oyuncular Yükleniyor", + "players": "Oyuncular" + }, + "serverScheduleConfig": { + "backup": "Sunucuyu Yedekle", + "basic": "Basit", + "children": "Bağlantılı Alt Görevler: ", + "command": "Komut", + "command-explain": "Hangi komutu çalıştırmamızı istiyorsunuz? '/'yi dahil etmeyin.", + "cron": "Cron", + "cron-explain": "Cron dizenizi girin -- NOT: 0 = Son seçenekte Pazartesi.", + "custom": "Özel Komut", + "days": "Günler", + "enabled": "Etkin", + "hours": "Saatler", + "interval": "Aralık", + "interval-explain": "Bu zamanlamanın ne sıklıkla uygulanmasını istiyorsunuz?", + "minutes": "Dakika", + "offset": "Gecikme Ofseti", + "offset-explain": "İlk görevi ateşledikten sonra bunu ateşlemek için ne kadar beklemeliyiz? (Saniye)", + "one-time": "Çalıştırdıktan sonra sil", + "parent": "Bir üst zamanlama seçin", + "parent-explain": "Bunu hangi zamanlama tetiklemeli?", + "reaction": "Zincirleme Reaksiyon", + "restart": "Sunucuyu Yeniden Başlat", + "select": "Basit / Cron / Zincirleme Reaksiyon Seçimi", + "start": "Sunucuyu Başlat", + "stop": "Sunucuyu Kapat", + "time": "Zaman", + "time-explain": "Zamanlamanın ne zaman uygulanmasını istiyorsunuz?" + }, + "serverSchedules": { + "action": "Eylem", + "areYouSure": "Zamanlanmış Görev Silinsin mi?", + "cancel": "İptal", + "cannotSee": "Her şeyi göremiyor musun?", + "cannotSeeOnMobile": "Tüm ayrıntılar için zamanlanmış bir göreve tıklamayı deneyin.", + "child": "ID ile alt zamanlama ", + "close": "Kapat", + "command": "Komut", + "confirm": "Onayla", + "confirmDelete": "Bu zamanlanmış görevi silmek istiyor musunuz? Bu geri alınamaz.", + "create": "Yeni Zamanlama Oluştur", + "cron": "Cron Dizesi", + "delete": "Sil", + "details": "Zamanlama Detayları", + "edit": "Düzenle", + "enabled": "Etkin", + "every": "Her", + "interval": "Aralık", + "name": "Ad", + "newSchedule": "Yeni Zamanlama", + "nextRun": "Sonraki Çalışma", + "no": "Hayır", + "no-schedule": "Şu anda bu sunucu için herhangi bir zamanlama bulunmamaktadır. Başlamak için: ", + "scheduledTasks": "Zamanlanmış Görevler", + "yes": "Evet" + }, + "serverStats": { + "cpuUsage": "CPU Kullanımı", + "description": "Açıklama", + "errorCalculatingUptime": "Çalışma Süresi Hesaplanırken Hata", + "memUsage": "Bellek Kullanımı", + "offline": "Çevrimdışı", + "online": "Çevrimiçi", + "players": "Oyuncular", + "serverStarted": "Sunucu Başlatıldı", + "serverStatus": "Sunucu Durumu", + "serverTime": "UTC Saati", + "serverTimeZone": "Sunucu Saat Dilimi", + "serverUptime": "Sunucu Çalışma Süresi", + "starting": "Gecikmeli Başlangıç", + "unableToConnect": "Bağlanılamıyor", + "version": "Sürüm" + }, + "serverTerm": { + "commandInput": "Komutunuzu girin", + "delay-explained": "Servis/ajan yakın zaman içerisinde başlatıldı ve minecraft sunucu örneğinin başlamasını erteliyor", + "importing": "İçe Aktarılıyor...", + "installing": "Kuruluyor...", + "restart": "Yeniden Başlat", + "sendCommand": "Komut gönder", + "start": "Başlat", + "starting": "Gecikmeli Başlangıç", + "stop": "Durdur", + "stopScroll": "Otomatik Kaydırmayı Durdur", + "updating": "Güncelleniyor..." + }, + "serverWizard": { + "absoluteServerPath": "Sunucunuzun mutlak konumu", + "absoluteZipPath": "Sunucunuzun mutlak konumu", + "addRole": "Sunucuyu Mevcut Rol(ler)e Ekle", + "autoCreate": "Hiçbiri seçilmezse Crafty bir tane yapacak!", + "bePatient": "Biz sunucuyu ' + (importing ? 'içe aktarırken' : 'indirirken') + ' lütfen sabırlı olun", + "buildServer": "Sunucuyu Oluştur!", + "clickRoot": "Kök dizinini seçmek için buraya tıklayın", + "close": "Kapat", + "defaultPort": "25565 varsayılan", + "downloading": "Sunucu İndiriliyor...", + "explainRoot": "Arşivin içinden sunucunuzun kök dizinini seçmek için lütfen aşağıdaki düğmeye tıklayın", + "importServer": "Mevcut Bir Sunucuyu İçe Aktar", + "importServerButton": "Sunucuyu İçe Aktar!", + "importZip": "Zip Dosyasından İçe Aktar", + "importing": "Sunucu İçe Aktarılıyor...", + "labelZipFile": "Zip Dosyanızı Seçin", + "maxMem": "Maksimum Bellek", + "minMem": "Minimum Bellek", + "myNewServer": "Benim Yeni Sunucum", + "newServer": "Yeni Sunucu Oluştur", + "quickSettings": "Hızlı Ayarlar", + "quickSettingsDescription": "Endişelenmeyin, bunları daha sonra değiştirebilirsiniz", + "resetForm": "Formu Sıfırla", + "save": "Kaydet", + "selectRole": "Rol(ler)i Seçin", + "selectRoot": "Arşiv Kök Dizinini Seçiniz", + "selectServer": "Bir Sunucu Seçin", + "selectType": "Sunucu Türü (Vanilla, Sunucular, Modlanmış, vb.)", + "selectVersion": "Bir Sürüm Seçin", + "selectZipDir": "Fermuarını açmamızı istediğiniz arşivdeki dizini seçin", + "serverJar": "Sunucu Çalıştırılabilir Dosyası", + "serverName": "Sunucu Adı", + "serverPath": "Sunucu Konumu", + "serverPort": "Sunucu Portu", + "serverSelect": "Sunucu Seçimi", + "serverType": "Server Tipi", + "serverUpload": "Sıkıştırılmış Sunucu Yükle", + "serverVersion": "Sunucu Sürümü", + "sizeInGB": "GB cinsinden boyut", + "uploadButton": "Dosya Yükle", + "uploadZip": "Sunucu İçe Aktarımı İçin Zip Dosyası Yükle", + "zipPath": "Sunucu Konumu" + }, + "sidebar": { + "contribute": "Katkıda Bulun", + "credits": "Krediler", + "dashboard": "Arayüz", + "documentation": "Dokümantasyon", + "inApp": "Uygulama İçi Dokümanlar", + "navigation": "Navigasyon", + "newServer": "Yeni Sunucu Oluştur", + "servers": "Sunucular" + }, + "startup": { + "almost": "Bitiriliyor. Sıkı tutun...", + "internals": "Crafty'nin dahili bileşenlerini konfigüre etme ve başlatma", + "internet": "İnternet bağlantısı kontrol ediliyor", + "server": "Başlatılıyor ", + "serverInit": "Sunucular Başlatılıyor", + "starting": "Crafty Başlatılıyor...", + "tasks": "Görev Zamanlayıcısı Başlatılıyor" + }, + "userConfig": { + "apiKey": "API Anahtarları", + "auth": "Yetkili mi? ", + "config": "Konfigürasyon", + "configArea": "Kullanıcı Konfigürasyon Alanı", + "configAreaDesc": "Tüm kullanıcı ayarlarınızı değiştireceğiniz yer burasıdır", + "confirmDelete": "Bu kullanıcıyı silmek istediğinizden emin misiniz? Bu işlem geri alınamaz.", + "craftyPermDesc": "Bu kullanıcının sahip olduğu Crafty izinleri: ", + "craftyPerms": "Crafty İzinleri: ", + "created": "Oluşturulma: ", + "delSuper": "Bir süper kullanıcıyı silemezsiniz", + "deleteUser": "Kullanıcıyı Sil: ", + "deleteUserB": "Kullanıcıyı Sil", + "enabled": "Etkin", + "gravDesc": "Bu e-posta katı bir şekilde sadece Gravatar™ kullanımı içindir. Crafty, hiçbir koşulda bu e-postayı Gravatar™'ınıza bakmak dışında herhangi bir amaçla kullanmayacaktır.", + "gravEmail": "Gravatar™ Emaili", + "lastIP": "Son IP: ", + "lastLogin": "Son Oturum Açma: ", + "lastUpdate": "Son Güncelleme: ", + "leaveBlank": "Şifreyi değiştirmeden kullanıcıyı düzenlemek için boş bırakın.", + "manager": "Yönetici", + "member": "Üye mi?", + "notExist": "Var olmayan bir şeyi silemezsiniz!", + "pageTitle": "Kullanıcıyı Düzenle", + "pageTitleNew": "Kullanıcı Oluştur", + "password": "Yeni Şifre", + "permName": "İzin Adı", + "repeat": "Şifreyi Onayla", + "roleName": "Rol Adı", + "selectManager": "Kullanıcı için Yönetici Seçin", + "super": "Süper Kullanıcı", + "userLang": "Kullanıcı Dili", + "userName": "Kullanıcı Adı", + "userNameDesc": "Bu kullanıcıya nasıl isimlendirmek istersiniz?", + "userRoles": "Kullanıcı Rolleri", + "userRolesDesc": "Bu kullanıcının üye olduğu roller.", + "userSettings": "Kullanıcı Ayarları", + "userTheme": "UI Teması", + "uses": "İzin verilen kullanım sayısı (-1==Sınır Yok)" + }, + "webhooks": { + "areYouSureDel": "Bu webhooku silmek istediğinizden emin misiniz?", + "areYouSureRun": "Bu webhooku test etmek istediğinizden emin misiniz?", + "backup_server": "Sunucu Yedeklemesi Tamamlandı", + "bot_name": "Bot Adı", + "color": "Renk Vurgusu Seçin", + "crash_detected": "Sunucu Çöktü", + "edit": "Düzenle", + "enabled": "Etkin", + "jar_update": "Sunucu Çalıştırılabilir Dosyası Güncellendi", + "kill": "Sunucu Öldürüldü", + "name": "Ad", + "new": "Yeni Webhook", + "newWebhook": "Yeni Webhook", + "no-webhook": "Şu anda bu sunucu için herhangi bir webhook bulunmamaktadır. Başlamak için:", + "run": "Webhooku Test Et", + "send_command": "Sunucu Komutu Alındı", + "start_server": "Sunucu Başlatıldı", + "stop_server": "Sunucu Durduruldu", + "trigger": "Tetikleyici", + "type": "Webhook Tipi", + "url": "Webhook URLsi", + "webhook_body": "Webhook Gövdesi", + "webhooks": "Webhooklar" + } +} diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json new file mode 100644 index 00000000..a02eddd7 --- /dev/null +++ b/app/translations/uk_UA.json @@ -0,0 +1,668 @@ +{ + "404": { + "contact": "Зв'язатись з Crafty Control підтримкою через Discord", + "notFound": "Сторінку не найдено!", + "unableToFind": "Нам не вдалося знайти сторінку, яку ви шукаєте. Спробуйте ще раз або поверніться й оновіть." + }, + "accessDenied": { + "accessDenied": "Доступ заборонено", + "contact": "Зв'язатись з Crafty Control підтримкою через Discord", + "contactAdmin": "Щоб отримати доступ до цього ресурсу, зверніться до адміністратора свого сервера або, якщо ви вважаєте, що вже маєте доступ до цього ресурсу, зверніться до служби підтримки.", + "noAccess": "У вас немає доступу до цього ресурсу." + }, + "apiKeys": { + "apiKeys": "API Ключі", + "auth": "Авторизовані?", + "buttons": "Кнопки", + "config": "Конфігурація", + "crafty": "Crafty: ", + "createNew": "Створити новий API Token", + "created": "Створений", + "deleteKeyConfirmation": "Ви дійсно бажаєте видалити API ключ? Це незворотня дія.", + "deleteKeyConfirmationTitle": "Видалення API ключ ${keyId}?", + "getToken": "Отримати Токен", + "name": "Ім'я", + "nameDesc": "Як ви хочете назвати даний API токен?", + "no": "Ні", + "pageTitle": "Редагування Користувацьких API ключів", + "permName": "Назва дозволу", + "perms": "Дозволи", + "server": "Сервер: ", + "superUser": "СуперЮзер", + "yes": "Так" + }, + "base": { + "doesNotWorkWithoutJavascript": "Увага: Crafty не працює належним чином коли JavaScript вимкненний!" + }, + "credits": { + "developmentTeam": "Команда Розробки", + "hugeDesc": "Величезне", + "pageDescription": "Без цих людей, не було б Crafty", + "pageTitle": "Подяка", + "patreonDesc": "нашим Patreon / Ko-fi підтримувачам!", + "patreonOther": "Інше", + "patreonSupporter": "Patreon / Ko-fi підтримка", + "patreonUpdate": "Останнє оновлення:", + "retiredStaff": "Ветерани", + "subscriberName": "Ім'я", + "subscriptionLevel": "Рівень", + "supportTeam": "Команда підтримки та документації", + "thankYou": "ДЯКУЮ", + "translationDesc": "нашій спільноті, хто перекладає! [ Активні = 🟢 Неактивні/Ветерани = ⚪ ]", + "translationName": "Ім'я", + "translationTitle": "Мовний переклад", + "translator": "Перекладачі" + }, + "customLogin": { + "apply": "Застосувати", + "backgroundUpload": "Фонове завантаження", + "customLoginPage": "Кастомізація сторінки входу", + "delete": "Видалити", + "labelLoginImage": "Вибрати свій фон входу", + "loginBackground": "Фон Вхідної сторінки", + "loginImage": "Завантаження свого фону для сторінки входу.", + "loginOpacity": "Виберіть прозорість фону сторінки входу", + "pageTitle": "Кастомна сторінка входу", + "preview": "Попередній перегляд", + "select": "Вибрати", + "selectImage": "Вибрати зображення" + }, + "dashboard": { + "actions": "Дії", + "allServers": "Всі сервери", + "avg": "Середнє", + "backups": "Бекапи", + "bePatientClone": "Будь ласка, будьте терплячі сервер копіюється/клонується.
Ця сторінка скоро оновиться", + "bePatientRestart": "Будь ласка, будьте терплячі сервер перезавантажується.
Ця сторінка скоро оновиться", + "bePatientStart": "Будь ласка, будьте терплячі сервер включається..
Ця сторінка скоро оновиться", + "bePatientStop": "Будь ласка, будьте терплячі сервер вимикається.
Ця сторінка скоро оновиться", + "cannotSee": "Нічого не бачите?", + "cannotSeeOnMobile": "Нічого не бачите на смартфоні?", + "cannotSeeOnMobile2": "Спробуйте прокрутити таблицю вбік.", + "clone": "Копіювати/клонувати", + "cloneConfirm": "Ви впевненні що бажаєте копіювати/клонувати даний сервер? Цей процес займе трішки часу.", + "cpuCores": "CPU Ядра", + "cpuCurFreq": "Швидкість CPU", + "cpuMaxFreq": "Максимальна швидкість CPU", + "cpuUsage": "Використання CPU", + "crashed": "Аварійне завершення", + "dashboard": "Панель", + "delay-explained": "Служба/агент нещодавно запущено та затримує запуск серверів minecraft", + "host": "Хост", + "installing": "Встановлення...", + "kill": "Вбити процес", + "killing": "Вбиваємо процес...", + "lastBackup": "Останній:", + "max": "Макс", + "memUsage": "Використання ОЗП", + "motd": "MOTD", + "newServer": "Створити новий сервер", + "nextBackup": "Наступний:", + "no-servers": "Зараз відсутні сервери. Щоб розпочати, натисніть.", + "offline": "Оффлайн", + "online": "Онлайн", + "players": "Гравці", + "restart": "Перезавантаження", + "sendingCommand": "Надіслати команду", + "server": "Сервер", + "servers": "Сервери", + "size": "Об'єм папки сервера", + "start": "Старт", + "starting": "Відкладений старт", + "status": "Статус", + "stop": "Стоп", + "storage": "Сховище", + "version": "Версія", + "welcome": "Ласкаво просимо у Crafty Controller" + }, + "datatables": { + "i18n": { + "aria": { + "sortAscending": ": активуйте, щоб сортувати стовпці за зростанням", + "sortDescending": ": активуйте, щоб сортувати стовпці за спаданням" + }, + "buttons": { + "collection": "Колекція ", + "colvis": "Видимість стовпців", + "colvisRestore": "Стандартна видимість", + "copy": "Копіювати", + "copyKeys": "Натисніть ctrl або u2318 + C щоб скопіювати таблицю в буфер обміну.

Для відміни, натисніть на це повідомлення або ESC.", + "copySuccess": { + "1": "Скопійовано 1 рядок в буфер обміну", + "_": "скопійовано %d рядки(-ів) в буфер обміну" + }, + "copyTitle": "Скопіювати в буфер обміну", + "csv": "CSV", + "excel": "Excel", + "pageLength": { + "-1": "Показати усі рядки", + "1": "Показати 1 рядок", + "_": "Показати %d рядки(-ів)" + }, + "pdf": "PDF", + "print": "Друк" + }, + "decimal": "", + "emptyTable": "Немає даних у цій таблиці", + "info": "Показ _START_ до _END_ з _TOTAL_ рядків", + "infoEmpty": "Показ 0 до 0 з 0 рядків", + "infoFiltered": "(відфльтровано з _MAX_ загалом рядків)", + "infoPostFix": "", + "lengthMenu": "Показати _MENU_ рядки", + "loadingRecords": "Завантаження...", + "paginate": { + "first": "Перший", + "last": "Останній", + "next": "Наступний", + "previous": "Попередній" + }, + "processing": "В процесі...", + "search": "Пошук:", + "select": { + "cells": { + "0": "Натисніть на комірку, щоб вибрати її", + "1": "%d комірку вибрано", + "_": "%d комірок вибрано" + }, + "columns": { + "0": "Натисніть на стовпець, щоб вибрати його", + "1": "%d стовпців вибрано", + "_": "%d стовпців вибрано" + }, + "rows": { + "0": "Натисність на рядок, щоб вибрати його", + "1": "%d рядок вибрано", + "_": "%d рядків вибрано" + } + }, + "thousands": ",", + "zeroRecords": "Не знайдено збігів в базі" + } + }, + "error": { + "agree": "Згодний", + "bedrockError": "Bedrock недоступний для скачування. Перевірте будь ласка", + "cancel": "Відміна", + "contact": "Зв'язатись з Crafty Control підтримкою через Discord", + "craftyStatus": "Crafty's статус", + "cronFormat": "Недійсний Cron формат знайдено", + "embarassing": "Ой, перепрошую, мені так соромно.", + "error": "Помилка!", + "eulaAgree": "Ви згодні?", + "eulaMsg": "Ви мусите погодитись з ", + "eulaTitle": "Ліцезнія EULA", + "fileError": "Тип файлу має бути зображення.", + "fileTooLarge": "Завантаження зупинено. Надто великий розмір файлу. Зв'яжіться зі системним адміністратором для допомоги.", + "hereIsTheError": "Ось помилка", + "installerJava": "Не вдалось встановити {} : Forge сервер потребує Java. Ми бачимо що, Java не інстальована. Будь ласка, встановіть java і лиш тоді сервер.", + "internet": "Ми виявили, що машина, на якій працює Crafty, не має підключення до Інтернету. Підключення клієнта до сервера може бути обмежено.", + "migration": "Основне серверне сховище Crafty переноситься в нове місце. На цей час усі запуски серверів призупинено. Зачекайте, поки ми завершимо цю міграцію.", + "no-file": "Здається, ми не можемо знайти потрібний файл. Ще раз перевірте шлях. Чи має Crafty належні дозволи?", + "noInternet": "Crafty має проблеми з доступом до Інтернету. Створення сервера вимкнено. Перевірте підключення до Інтернету та оновіть сторінку.", + "noJava": "Сервер {} не вдалося запустити з кодом помилки: ми виявили, що Java не встановлено. Установіть Java, а потім запустіть сервер.", + "not-downloaded": "Здається, ми не можемо знайти ваш виконуваний файл. Чи завершилось завантаження? Чи встановлено дозволи на виконуваний файл?", + "portReminder": "Ми виявили це вперше {} був запущений. Обов’язково перенаправте порт {} через ваш маршрутизатор/брандмауер, щоб зробити це доступним з Інтернету.", + "privMsg": "і ", + "serverJars1": "API сервера JAR недоступний. Будь ласка, перевірте", + "serverJars2": "для найактуальнішої інформації.", + "start-error": "Сервер {} не запустився через помилку: {}", + "superError": "Ви маєте мати права суперюзера для виконання даного завдання.", + "terribleFailure": "Яка Жахлива Невдача!" + }, + "footer": { + "allRightsReserved": "Всі права захищено", + "copyright": "Захищено Авторським правом", + "version": "Версія" + }, + "login": { + "forgotPassword": "Забули пароль", + "login": "Вхід", + "password": "Пароль", + "username": "Логін", + "viewStatus": "Список серверів" + }, + "notify": { + "activityLog": "Логи активностей", + "backupComplete": "Бекап успішно завершено для сервера {}", + "backupStarted": "Бекап успішно розпочато для сервера {}", + "downloadLogs": "Завантажити логи для підтримки?", + "finishedPreparing": "Ми підготували логи. Будь ласка натисніть завантажити", + "logout": "Вихід", + "preparingLogs": "Будь ласка зачекайте поки ми підготуємо для вас логи... Ми надішлемо вам сповіщення коли усе буде готово. Це може зайняти трішки часу для великих проєктів.", + "supportLogs": "Логи для підтримки" + }, + "offline": { + "offline": "Оффлайн", + "pleaseConnect": "Будь ласка підключіться до інтернету, щоб використовувати Crafty." + }, + "panelConfig": { + "adminControls": "Адмінський контроль", + "allowedServers": "Доступні сервери", + "apply": "Застосувати", + "assignedRoles": "Призначені ролі", + "cancel": "Відмінити", + "clearComms": "Очистити невиконані команди", + "custom": "Кастомізація Crafty", + "delete": "Видалити", + "edit": "Редагувати", + "enableLang": "Увімкнути усі мови", + "enabled": "Увімкненно", + "globalExplain": "Де Crafty зберігає усі файли сервера (Шлях до серверів можна знайти за допомогою /servers/[uuid сервера])", + "globalServer": "Глобальна папка серверів", + "json": "Config.json", + "match": "Паролі мають співпадати", + "newRole": "Додати нову роль", + "newUser": "Додати нового користувача", + "noMounts": "Show no Mounts on Dash", + "pageTitle": "Панель конфігурації", + "role": "Роль", + "roleUsers": "Ролі юзерів", + "roles": "Ролі", + "save": "Зберегти", + "select": "Вибрати", + "superConfirm": "Продовжуйте, лише якщо ви хочете, щоб цей користувач мав доступ до ВСЬОГО (усіх облікових записів користувачів, серверів, налаштувань панелі тощо). Вони навіть можуть відкликати ваші права суперкористувача. Оберігайтесь Шахраїв!", + "superConfirmTitle": "Активувати суперюзера? Ви впевненні?", + "title": "Конфігурація Crafty", + "user": "Користувач", + "users": "Користувачі" + }, + "rolesConfig": { + "config": "Конфігурація ролей", + "configDesc": "Тут ви можете змінити конфігурацію своєї ролі", + "configUpdate": "Востаннє оновлено: ", + "created": "Створено: ", + "delRole": "Видалити роль", + "doesNotExist": "Ви не можете видалити те, чого не існує!", + "pageTitle": "Редагувати роль", + "pageTitleNew": "Нова роль", + "permAccess": "Доступ?", + "permName": "Назва прав", + "permsServer": "Дозволи, які ця роль має для вказаних серверів", + "roleConfigArea": "Область конфігурації ролі", + "roleDesc": "Як ви хочете називати цю роль?", + "roleName": "Назва ролі: ", + "rolePerms": "Права ролі", + "roleServers": "Доступні сервери", + "roleTitle": "Налаштування ролі", + "roleUserName": "Назва користувача", + "roleUsers": "Ролі користувачів: ", + "selectManager": "Виберіть менеджера для цієї ролі", + "serverAccess": "Доступ?", + "serverName": "Назва сервера", + "serversDesc": "сервери які доступні для цієї ролі" + }, + "serverBackups": { + "after": "Виконати команду після завершення бекапу", + "backupAtMidnight": "Авто-бекап опівночі?", + "backupNow": "Запустити бекап!", + "backupTask": "Бекап запущено.", + "before": "Виконати команду перед початком бекапу", + "cancel": "Відмінити", + "clickExclude": "Додати винятки", + "compress": "Стиснути бекап", + "confirm": "Прийняти", + "confirmDelete": "Ви дійсно бажаєте видати бекап? Ця дія незворотня.", + "confirmRestore": "Ви впевненні що бажаєте відновити даний бекап? При відновленні сервер буде вимкнуто та відновлено за допомогою даного бекапу, минулі файли будуть втрачені!", + "currentBackups": "Поточні бекапи", + "delete": "Видалити", + "destroyBackup": "Видалити бекап \" + file_to_del + \"?", + "download": "Завантажити", + "excludedBackups": "Винятки: ", + "excludedChoose": "Виберіть папки які бажаєте додати у винятки", + "exclusionsTitle": "Бекап винятки", + "maxBackups": "Максимум бекапів", + "maxBackupsDesc": "Crafty не зможе зберігати більше ніж N бекапів, видалятиме старі (введіть 0 для зберігання усіх бекапів)", + "options": "Налаштування", + "path": "Шлях", + "restore": "Відновити", + "restoring": "Відновлення бекапу. Це може зайняти деякий час. Будь ласка будьте терплячі.", + "save": "Зберегти", + "shutdown": "Вимикати сервер на час бекапу", + "size": "Розмір", + "storageLocation": "Місце зберігання", + "storageLocationDesc": "Де ви бажаєте зберігати бекапи?" + }, + "serverConfig": { + "bePatientDelete": "Будь ласка зачекайте поки Crafty видалить сервер з панелі. Ця сторінка закриється через кілька секунд.", + "bePatientDeleteFiles": "Будь ласка зачекайте поки Crafty видалить сервер з панелі та видалить усі його файли. Ця сторінка закриється через кілька секунд.", + "bePatientUpdate": "Please be patient while we update the server. Download times can vary depending upon your internet speeds.
This screen will refresh in a moment", + "cancel": "Відміна", + "crashTime": "Краш таймаут", + "crashTimeDesc": "Скільки часу чекати, перш ніж ми вважатимемо, що ваш сервер крашнувся?", + "deleteFilesQuestion": "Видалити файли сервера з машини?", + "deleteFilesQuestionMessage": "Чи бажаєте щоб Crafty видалив усі сервери та файли до них з машини?

Включаючи бекапи.", + "deleteServer": "Видалити сервер", + "deleteServerQuestion": "Видалити сервер?", + "deleteServerQuestionMessage": "Ви впевнені що бажаєте видалити сервер? Назад вороття не буде...", + "exeUpdateURL": "URL-адреса оновлення сервера", + "exeUpdateURLDesc": "Пряме посилання для завантаження оновлень.", + "ignoredExits": "Ігнорувати дані коди помилок", + "ignoredExitsExplain": "Коди виходу виявлення крашу сервера Crafty має ігнорувати як звичайну «зупинку» (розділені комами)", + "javaNoChange": "Автоматичний вибір", + "javaVersion": "Вибрати іншу Java версію", + "javaVersionDesc": "Якщо ви збираєтеся замінити Java, переконайтеся, що ваш поточний шлях Java у «команді виконання» взято в лапки (за замовчуванням змінна «java» виключена)", + "noDelete": "Ні, повернутись назад", + "noDeleteFiles": "Ні, видалити тільки з панелі", + "removeOldLogsAfter": "Видалити старі логи після", + "removeOldLogsAfterDesc": "Скільки днів має пройти щоб видалити старі логи? (0 це вимкненно)", + "save": "Зберегти", + "sendingDelete": "Видалення сервера", + "sendingRequest": "Надсилання вашого запиту...", + "serverAutoStart": "Сервер Авто-старт", + "serverAutostartDelay": "Сервер Авто-старт затримка", + "serverAutostartDelayDesc": "Затримка Авто-старту сервера (Якщо увімкнуто раніше)", + "serverCrashDetection": "Детектор крашу сервера", + "serverExecutable": "Виконуваний файл Серверу", + "serverExecutableDesc": "Це виконуваний файл для запуску сервера", + "serverExecutionCommand": "Виконувана команда запуску сервера", + "serverExecutionCommandDesc": "Буде запущено у прихованому терміналі", + "serverIP": "IP-адреса сервера", + "serverIPDesc": "IP-адреса Crafty для статистики (Спробуй справжню IP-адресу, або 127.0.0.1 якщо маєте проблеми)", + "serverLogLocation": "Логи сервера", + "serverLogLocationDesc": "Шлях до логів сервера", + "serverName": "Назва сервера", + "serverNameDesc": "Як назвати даний сервер?", + "serverPath": "Робоча папка сервера", + "serverPathDesc": "Повний шлях до папки сервера (не посилання на виконуваний файл)", + "serverPort": "Порт сервера", + "serverPortDesc": "Цей порт призначений для статистики Crafty", + "serverStopCommand": "Команда зупинки сервера", + "serverStopCommandDesc": "Команда яка буде надсилатись, щоб зупинити сервер", + "showStatus": "Показувати на публічній сторінці статус", + "shutdownTimeout": "Час відклику зупинки", + "statsHint1": "Цей порт на якому працює сервер. Це потрібно лиш для того щоб Crafty міг виводити статистику для цього сервера.", + "statsHint2": "Це не змінює порт вашого сервера. Ви мусите власноруч змінити налаштування в server.properties або іншому конфігураційному файлі.", + "stopBeforeDeleting": "Будь ласка зупиніть сервер перед тим як видаляти його", + "timeoutExplain1": "Скільки Crafty має чекати вимкнення вашого сервера після запуску", + "timeoutExplain2": "команди перед тим як примусово його вимкнути?", + "update": "Оновити виконуваний файл", + "yesDelete": "Так, видалити", + "yesDeleteFiles": "Так, видалити файли" + }, + "serverConfigHelp": { + "desc": "Тут можна змінити конфігурацію вашого сервера.", + "perms": [ + "Рекомендовано НЕ змінювати шлях до сервера який створив Crafty.", + "Зміна шляхів МОЖЕ зламати щось, особливо в операційних системах типу Linux, де дозволи на файли більш заблоковані.", + "

", + "Якщо ви вважаєте, що потрібно змінити шлях до сервера, ви можете це зробити, але обов'язково надайте \"crafty\" користувачеві дозвіл читати/записувати шлях до сервера.", + "
", + "
", + "У Linux це найкраще зробити, виконавши наступне:
", + "", + " sudo chown crafty:crafty /шлях/до/вашого/сервера -R
", + " sudo chmod 2775 /шлях/до/вашого/сервера -R
", + "
" + ], + "title": "Область конфігурації сервера" + }, + "serverDetails": { + "backup": "Бекап", + "config": "Конфігурація", + "files": "Файли", + "filter": "Фільтри логів", + "filterList": "Відфільтровані слова", + "logs": "Логи", + "metrics": "Графік", + "playerControls": "Керування Гравцями", + "reset": "Повернутись нагору", + "schedule": "Розклад", + "serverDetails": "Деталі сервера", + "terminal": "Термінал" + }, + "serverFiles": { + "clickUpload": "Натисність тут щоб обрати ваші файли", + "close": "Закрити", + "createDir": "Створити папку", + "createDirQuestion": "Як назвати створену вашу директорію?", + "createFile": "Створити файл", + "createFileQuestion": "Як назвати створений вами файл?", + "default": "За замовчуванням", + "delete": "Видалити", + "deleteItemQuestion": "Ви впевнені що бажаєте видалити \" + name + \"?", + "deleteItemQuestionMessage": "Ви видаляєте \\\"\" + path + \"\\\"!

Це незворотня дія!", + "download": "Завантажити", + "editingFile": "Редагувати файл", + "error": "Помилка отримання файлів", + "fileReadError": "Помилка читання файлу", + "files": "Файли", + "keybindings": "Прив'язки клавіш", + "loadingRecords": "Завантаження файлів...", + "noDelete": "Ні", + "noscript": "Файловий менеджер не працює без JavaScript", + "rename": "Перейменувати", + "renameItemQuestion": "Яка нова назва файлу?", + "save": "Зберегти", + "size": "Перемкнути розмір редактора", + "stayHere": "НЕ ВИХОДЬТЕ З ЦІЄЇ СТОРІНКИ!", + "unsupportedLanguage": "Увага: Цей файл не підтримується", + "unzip": "Розархівувати", + "upload": "Вивантажити", + "uploadTitle": "Вивантажити файл до: ", + "waitUpload": "Будь ласка зачекати поки ми завантажимо вибрані файли... Це займе трішки часу.", + "yesDelete": "Так, я розумію наслідки" + }, + "serverMetrics": { + "resetZoom": "Скинути приближення", + "zoomHint1": "Щоб збільшити графік, утримуйте клавішу Shift, а потім використовуйте колесо прокручування.", + "zoomHint2": "Або утримуйте клавішу Shift, а потім клацніть і перетягніть область, яку ви хочете збільшити." + }, + "serverPlayerManagement": { + "bannedPlayers": "Заблоковані користувачі", + "loadingBannedPlayers": "Завантаження заблокованих користувачів", + "players": "Користувачі" + }, + "serverScheduleConfig": { + "backup": "Бекап серверу", + "basic": "Базова", + "children": "Зв’язані дочірні завдання: ", + "command": "Команда", + "command-explain": "Яку команду потрібно виконати? Не враховується '/'", + "cron": "Cron", + "cron-explain": "Введіть свій рядок cron -- ПРИМІТКА: 0 = понеділок в останньому варіанті.", + "custom": "Користувацька команда", + "days": "Дні", + "enabled": "Увімкнути", + "hours": "Години", + "interval": "Інтервал", + "interval-explain": "Як часто ви хочете виконувати це заплановане завдання?", + "minutes": "Хвилини", + "offset": "Зсув затримки", + "offset-explain": "Скільки часу ми повинні чекати, щоб запустити це після запуску першого завдання? (Секунди)", + "one-time": "Видалити після виконання", + "parent": "Виберіть батьківське відкладене завдання", + "parent-explain": "Який з інших завдань має викликати цей?", + "reaction": "Реакція", + "restart": "Перезавантаження сервера", + "select": "Базова / Cron / Ланцюгова реакція", + "start": "Старт серверу", + "stop": "Вимкнення серверу", + "time": "Час", + "time-explain": "О котрій годині ви хочете виконувати свій розклад?" + }, + "serverSchedules": { + "action": "Дія", + "areYouSure": "Видалити заплановане завдання?", + "cancel": "Відмінити", + "cannotSee": "Нічого не бачите?", + "cannotSeeOnMobile": "Спробуйте натиснути на заплановане завдання щоб побачити деталі.", + "child": "Дочірнє заплановане завдання, його ID ", + "close": "Закрити", + "command": "Команда", + "confirm": "Прийняти", + "confirmDelete": "Ви впевненні що бажаєте видалити дане заплановане завдання? Це незворотня дія.", + "create": "Створити нове заплановане завдання", + "cron": "Cron рядок", + "delete": "Видалити", + "details": "Деталі запланованих завдань", + "edit": "Редагувати", + "enabled": "Увімкнуто", + "every": "Кожен", + "interval": "Інтервал", + "name": "Назва", + "newSchedule": "Нове завдання", + "nextRun": "Настуне виконання", + "no": "Ні", + "no-schedule": "Зараз жодного запланованого завдання для цього сервера, щоб розпочати натисніть", + "scheduledTasks": "Заплановані завдання", + "yes": "Так" + }, + "serverStats": { + "cpuUsage": "Використання Процесора", + "description": "Опис", + "errorCalculatingUptime": "Підрахунок помилок аптайму", + "memUsage": "Використання ОПЗ", + "offline": "Оффлайн", + "online": "Онлайн", + "players": "Гравці", + "serverStarted": "Сервер запущено", + "serverStatus": "Статус сервера", + "serverTime": "UTC час", + "serverTimeZone": "Часовий пояс серверу", + "serverUptime": "Аптайм сервера", + "starting": "Відкладений запуск", + "unableToConnect": "Неможливо підключитись", + "version": "Версія" + }, + "serverTerm": { + "commandInput": "Введіть команду", + "delay-explained": "Сервіс/агент щойно запустився і потрібно трішки часу для початку старту серверів", + "importing": "Імпортування...", + "installing": "Встановлення...", + "restart": "Рестарт", + "sendCommand": "Надіслати", + "start": "Старт", + "starting": "Відкладений старт", + "stop": "Стоп", + "stopScroll": "Зупинити автоматичне прокручування", + "updating": "Оновлення..." + }, + "serverWizard": { + "absoluteServerPath": "Повний шлях до папки сервера", + "absoluteZipPath": "Повний шлях до архіву сервера", + "addRole": "Додати сервер до Наявної ролі(-ей)", + "autoCreate": "Якщо жоден не вибраний, Crafty зробить один!", + "bePatient": "Будь ласка зачекайте поки ми ' + (importing ? 'імпортуємо' : 'завантажуємо') + ' сервер", + "buildServer": "Зібрати сервер!", + "clickRoot": "Натисність щоб обрати корневу директорію сервера", + "close": "Закрити", + "defaultPort": "25565 за замовчуванням", + "downloading": "Завантажується сервер...", + "explainRoot": "Натисніть кнопку нижче, щоб вибрати кореневий каталог вашого сервера всередині архіву", + "importServer": "Імпортувати готовий сервер", + "importServerButton": "Імпортувати сервер!", + "importZip": "Імпортувати з Архіву(Zip) ", + "importing": "Імпортування сервера...", + "labelZipFile": "Виберіть архів (Zip)", + "maxMem": "Максимум пам'яті", + "minMem": "Мінімум пам'яті", + "myNewServer": "Мій новий сервер (краще називати латиницею)", + "newServer": "Створити новий сервер", + "quickSettings": "Швидкі налаштування", + "quickSettingsDescription": "Не хвилюйтесь, ви можете це змінити це пізніше", + "resetForm": "Скинути форму", + "save": "Зберегти", + "selectRole": "Вибрати роль(-і)", + "selectRoot": "Вибрати корневу папку архіву", + "selectServer": "Вибрати сервер", + "selectType": "Типи серверів (Ваніла, Ванільні з плагінами, Модові, інші)", + "selectVersion": "Вибрати версію", + "selectZipDir": "Виберіть каталог в архіві, з якого ви хочете розархівувати файли", + "serverJar": "Виконуваний файл серверу (.jar)", + "serverName": "Назва серверу", + "serverPath": "Шлях сервера", + "serverPort": "Порт сервера", + "serverSelect": "Вибрати сервер", + "serverType": "Тип серверу", + "serverUpload": "Вивантажити архівований сервер", + "serverVersion": "Версія сервера", + "sizeInGB": "Об'єм пам'яті в ГБ", + "uploadButton": "Вивантажити", + "uploadZip": "Вивантажити архів(.zip) для імпорту сервера", + "zipPath": "Шлях архіву сервера" + }, + "sidebar": { + "contribute": "Внести свій внесок", + "credits": "Подяка", + "dashboard": "Панель", + "documentation": "Документація", + "inApp": "Швидка документація", + "navigation": "Навігація", + "newServer": "Створити новий сервер", + "servers": "Сервери" + }, + "startup": { + "almost": "Закінчуємо. Тримайся міцніше...", + "internals": "Налаштування та запуск внутрішніх компонентів Crafty ", + "internet": "Перевірка доступу до інтернету", + "server": "Ініціалізація ", + "serverInit": "Ініціалізація серверів", + "starting": "Crafty запускається...", + "tasks": "Запуск відкладених завдань" + }, + "userConfig": { + "apiKey": "API Ключі", + "auth": "Авторизовані? ", + "config": "Конфігурація", + "configArea": "Область конфігурації користувача", + "configAreaDesc": "Тут ви можете змінити всі налаштування користувача", + "confirmDelete": "Ви впевненні що бажаєте видалити даного користувача? Це незворотня дія.", + "craftyPermDesc": "Дозволи Crafty для цього користувача", + "craftyPerms": "Доступ Crafty: ", + "created": "Створений: ", + "delSuper": "Ви не можете видалити суперюзера!", + "deleteUser": "Видалити користувача: ", + "deleteUserB": "Видалити користувача", + "enabled": "Увімкнуто", + "gravDesc": "Цей електронний лист призначений виключно для використання з Gravatar™. Crafty ні за яких обставин не використовуватиме цю електронну пошту для будь-яких інших цілей, крім пошуку вашого Gravatar™", + "gravEmail": "Gravatar™ пошта", + "lastIP": "Остання IP-адреса: ", + "lastLogin": "Остання авторизація: ", + "lastUpdate": "Останнє оновлення: ", + "leaveBlank": "Щоб редагувати користувача без зміни пароля, залиште це поле пустим.", + "manager": "Менеджер", + "member": "Учасник?", + "notExist": "Ви не можете видалити те, чого не існує!", + "pageTitle": "Редагувати користувача", + "pageTitleNew": "Створити користувача", + "password": "Новий пароль", + "permName": "Назва дозволу", + "repeat": "Підтвердити пароль", + "roleName": "Назва ролі", + "selectManager": "Вказати менеджера для цього користувача", + "super": "СуперЮзер", + "userLang": "Мова користувача", + "userName": "Ім'я користувача", + "userNameDesc": "Як ви хочете назвати даного користувача?", + "userRoles": "Ролі користувача", + "userRolesDesc": "Виберіть ролі до яких належить користувач.", + "userSettings": "Налаштування користувача", + "userTheme": "Тема інтерфейсу", + "uses": "Дозволена кількість використань(-1==Без ліміту)" + }, + "webhooks": { + "areYouSureDel": "Ви впевнені, що хочете видалити цей Вебхук?", + "areYouSureRun": "Ви впевнені, що хочете перевірити цей Вебхук?", + "backup_server": "Бекап серверу завершено!", + "bot_name": "Назва бота", + "color": "Вибрати колір", + "crash_detected": "Сервер впав", + "edit": "Редагувати", + "enabled": "Увімкнуто", + "jar_update": "Виконуваний файл сервера оновлено", + "kill": "Сервер вбито", + "name": "Назва", + "new": "Новий Вебхук", + "newWebhook": "Новий Вебхук", + "no-webhook": "Зараз для цього сервера немає Вебхуків. Щоб почати, натисніть", + "run": "Тестовий запуск Вебхука", + "send_command": "Серверну команду отримано", + "start_server": "Сервер запущено", + "stop_server": "Сервер зупинено", + "trigger": "Тріггер", + "type": "Тип Вебхуку", + "url": "URL-адреса Вебхука", + "webhook_body": "Код Вебхука", + "webhooks": "Вебхуки" + } +} From b3316a7d8c0ae484b20359065219478157be6c41 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Fri, 26 Jan 2024 12:53:35 -0600 Subject: [PATCH 31/84] update translations for 4.2.3 --- app/translations/de_DE.json | 1 + app/translations/fr_FR.json | 1 + app/translations/lv_LV.json | 1 + app/translations/nl_BE.json | 1 + app/translations/pl_PL.json | 1 + app/translations/th_TH.json | 1 + app/translations/tr_TR.json | 1 + app/translations/uk_UA.json | 1 + app/translations/zh_CN.json | 1 + 9 files changed, 9 insertions(+) diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index 11311bb0..1a7f8995 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Bitte haben Sie etwas Geduld, während wir Ihren Server aus dem Crafty-Panel entfernen und alle Dateien löschen. Dieser Bildschirm wird in wenigen Augenblicken geschlossen.", "bePatientUpdate": "Bitte haben Sie etwas Geduld, während wir den Server aktualisieren. Die Downloadzeiten können je nach Ihrer Internetgeschwindigkeit variieren.
Dieser Bildschirm wird sich in einem Moment aktualisieren", "cancel": "Abbrechen", + "countPlayers": "Server in die Gesamtspielerzahl einbeziehen", "crashTime": "Zeitüberschreitung nach Absturz", "crashTimeDesc": "Wie lange soll Crafty warten, bevor Crafty den Server als abgestürzt betrachtet?", "deleteFilesQuestion": "Serverdateien vom Rechner löschen?", diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index 112de289..aa45a69b 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Merci de patienter pendant la suppression du serveur du tableau de bord de Crafty et des fichiers de la machine hôte. Cet écran se fermera dans quelques instants.", "bePatientUpdate": "Merci de patienter pendant la mise à jour du Serveur. La durée de téléchargement dépend de votre vitesse de connexion internet.
Cet écran se mettra à jour dans quelques instants", "cancel": "Annuler", + "countPlayers": "Inclure ce serveur dans le nombre total de joueurs", "crashTime": "Délai de plantage", "crashTimeDesc": "Combien de temps attendre avant de considérer que le serveur a crash ?", "deleteFilesQuestion": "Supprimer les fichiers de la machine ?", diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index 95d2ffae..354a0e54 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -328,6 +328,7 @@ "bePatientDeleteFiles": "Lūdzu esiet pacietīgs, kamēr mēs noņemam jūsu serveri no Crafty paneļa un izdzēšam visus failus. Šis ekrāns aizvērsies pēc maza brītiņa.", "bePatientUpdate": "Lūdzu esiet pacietīgi, kamēr mēs atjauninām serveri. Lejupielādes laiki var mainīties atkarībā no tīkla savienojuma ātruma.
Šis ekrāns atjaunosies pēc brīža", "cancel": "Atcelt", + "countPlayers": "Pieskaitīt serveri pie kopējā spēlētāju skaita", "crashTime": "Avārijas Taimouts", "crashTimeDesc": "Cik ilgi mums nogaidīt pirms mēs uzskatām serveri kā avarējušu?", "deleteFilesQuestion": "Dzēst servera failus no ierīces?", diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index bed0f894..c9414bbe 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Even geduld terwijl we uw server uit het Crafty-paneel verwijderen, en alle bestanden verwijderen. Dit scherm wordt over enkele ogenblikken gesloten.", "bePatientUpdate": "Even geduld terwijl we de server updaten. De downloadtijden kunnen variëren, afhankelijk van je internetsnelheden.
Dit scherm wordt zo vernieuwd", "cancel": "Annuleren", + "countPlayers": "Server opnemen in het totale spelersaantal", "crashTime": "Crash Timeout", "crashTimeDesc": "Hoe lang moet er gewacht worden voordat we uw server als gecrasht beschouwen?", "deleteFilesQuestion": "Serverbestanden van de machine verwijderen?", diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index 2b9ce56d..86f8f9cb 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Poczekaj, aż usuniemy twój serwer i jego pliki. Strona za chwilę się zamknie.", "bePatientUpdate": "Poczekaj kiedy my aktualizujemy twój serwer. Pobieranie zależy od prędkości twojego internetu.
Strona się odświeży za chwile.", "cancel": "Anuluj", + "countPlayers": "Wlicz serwer do całkowitej liczby graczy", "crashTime": "Crash serwera wyszedł poza limit czasu", "crashTimeDesc": "Jak długo powinniśmy poczekać zanim uznać serwer za zcrashowany?", "deleteFilesQuestion": "Usuń pliki serwera z maszyny?", diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index f919236a..3d2826ea 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "โปรดอดทนรอในขณะที่เราลบเซิร์ฟเวอร์ของคุณออกจากแผง Crafty และลบไฟล์ทั้งหมด หน้าต่องนี้จะปิดลงในอีกสักครู่", "bePatientUpdate": "กรุณารออย่างใจเย็นในขณะที่เราอัปเดตเซิร์ฟเวอร์ เวลาในการดาวน์โหลดอาจแตกต่างกันไปขึ้นอยู่กับความเร็วอินเทอร์เน็ตของคุณ
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", "cancel": "ยกเลิก", + "countPlayers": "Include server in total player count", "crashTime": "ผิดพลาด หมดเวลา", "crashTimeDesc": "เราควรรอนานแค่ไหนก่อนที่จะพิจารณาว่าเซิร์ฟเวอร์ของคุณขัดข้อง?", "deleteFilesQuestion": "ลบไฟล์เซิร์ฟเวอร์ออกจากเครื่อง?", diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index 1ab75a0d..9ab3a6c8 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Sunucunuzu Crafty panelinden kaldırırken ve dosyalarını silerken lütfen sabırlı olun. Bu ekran birazdan kapanacaktır.", "bePatientUpdate": "Sunucuyu güncellerken lütfen sabırlı olun. İndirme süreleri internet hızınıza bağlı olarak değişebilir.
Bu ekran birazdan kendini yenileyecektir", "cancel": "İptal", + "countPlayers": "Sunucuyu toplam oyuncu sayısına dahil et.", "crashTime": "Çökme Zaman Aşımı", "crashTimeDesc": "Sunucunuzun çöktüğünü varsaymadan önce ne kadar beklemeliyiz?", "deleteFilesQuestion": "Sunucu dosyaları makineden silinsin mi?", diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json index a02eddd7..a7018a5f 100644 --- a/app/translations/uk_UA.json +++ b/app/translations/uk_UA.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "Будь ласка зачекайте поки Crafty видалить сервер з панелі та видалить усі його файли. Ця сторінка закриється через кілька секунд.", "bePatientUpdate": "Please be patient while we update the server. Download times can vary depending upon your internet speeds.
This screen will refresh in a moment", "cancel": "Відміна", + "countPlayers": "Враховувати сервер до загальної кількості гравців", "crashTime": "Краш таймаут", "crashTimeDesc": "Скільки часу чекати, перш ніж ми вважатимемо, що ваш сервер крашнувся?", "deleteFilesQuestion": "Видалити файли сервера з машини?", diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index b8689b2a..ffac7b3b 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "请耐心等待,我们正在从 Crafty 面板中移除服务器并删除所有文件。稍后此页面会关闭。", "bePatientUpdate": "请耐心等待,我们正在更新服务器。下载时长可能因您的网络速度而异。
稍后此页面会刷新", "cancel": "取消", + "countPlayers": "在玩家总数中包含服务器", "crashTime": "崩溃超时", "crashTimeDesc": "我们应该在考虑您的服务器已崩溃之前等待多久?", "deleteFilesQuestion": "从设备上删除服务器文件?", From f28a211b6655184f9778fdb72ed2bebeb1f17b10 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Fri, 26 Jan 2024 13:19:07 -0600 Subject: [PATCH 32/84] Update translatiosn for 4.2.3 --- app/translations/lol_EN.json | 1 + 1 file changed, 1 insertion(+) diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index a2368a84..4836501b 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "PLZ BE PAITENT I EAT UR SERVR AN EAT AW TEH YUMMI FISH. DIS SCRIEN WILL REFRESH SOONZ", "bePatientUpdate": "PLZ BE PAITENTZ WE GET TEH NEWZ SERVER. HUNTING TEIMZ CAN VARY IF UR INTERWEBZ IZ POOP.
DIS SCRIEN WILL REFRESH SOONZ", "cancel": "STAHP", + "countPlayers": "COUNT ALL DA HOOMANS IN TOTAL PLAYERZ", "crashTime": "DUN GOOF TIMEOUT", "crashTimeDesc": "HOW LONG SHUD WE WAIT BEFORE WE CONSIDR UR SERVR HAS DUN GOOFD?", "deleteFilesQuestion": "EAT SERVR FISH TOO?", From 9fed45d147f33ce632b1c11ab8152a1491b6f8de Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 26 Jan 2024 15:29:12 -0500 Subject: [PATCH 33/84] Only allow access to panel config --- app/classes/web/panel_handler.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 8ac827c3..52d85acf 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -286,6 +286,8 @@ class PanelHandler(BaseHandler): ) tz = "Europe/London" + page = "panel_config" + page_data: t.Dict[str, t.Any] = { # todo: make this actually pull and compare version data "update_available": self.helper.update_available, From bb18400b90dfbd8b9bb8769c29d22a082b8e827e Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Fri, 26 Jan 2024 15:29:25 -0500 Subject: [PATCH 34/84] Fix schedule firing too early --- app/classes/controllers/users_controller.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index eb74f15c..80a431bf 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -1,6 +1,7 @@ import logging import typing as t import datetime +from datetime import timedelta from apscheduler.schedulers.background import BackgroundScheduler from app.classes.models.servers import HelperServers @@ -384,12 +385,12 @@ class UsersController: ) self.scheduler.add_job( self.stop_anti_lockout, - "interval", - hours=1, + "date", id="anti-lockout-watcher", - start_date=datetime.datetime.now(), + run_date=datetime.datetime.now() + timedelta(hours=1), ) def stop_anti_lockout(self): + print("IN STOP") self.scheduler.remove_all_jobs() self.users_helper.remove_user(self.get_id_by_name("anti-lockout-user")) From 1da483a2892ff42c861ebc6d9e362691caba6534 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Fri, 26 Jan 2024 17:19:58 -0600 Subject: [PATCH 35/84] Update translation for 4.2.3 --- app/translations/he_IL.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index 73e7032a..cff35559 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -327,6 +327,7 @@ "bePatientDeleteFiles": "אנא חכו בסבלנות בזמן שאנו מסירים את השרת שלך מהחלונית קראפטי ומוחקים את כל הקבצים. מסך זה ייסגר בעוד מספר רגעים.", "bePatientUpdate": "אנא חכו בסבלנות בזמן שאנו מעדכנים את השרת. זמני ההורדה עשויים להשתנות בהתאם למהירויות האינטרנט שלך.
מסך זה יתרענן בעוד רגע", "cancel": "ביטול", + "countPlayers": "הכללת השרת במספר המשחקנים הכולל", "crashTime": "פסק זמן לקריסה", "crashTimeDesc": "כמה זמן עלינו להמתין לפני שנראה שהשרת שלך קרס?", "deleteFilesQuestion": "למחוק קבצי שרת מהמחשב?", @@ -500,8 +501,10 @@ "every": "כל", "interval": "מרווח", "name": "שם", + "newSchedule": "לוח זמנים חדש", "nextRun": "הריצה הבאה", "no": "לא", + "no-schedule": "אין כרגע לוחות זמנים מוגדרים עבור שרת זה. כדי להתחיל, לחץ", "scheduledTasks": "משימות מתוזמנות", "yes": "כן" }, @@ -652,6 +655,8 @@ "kill": "השרת נסגר", "name": "שם", "new": "Webhook חדש", + "newWebhook": "וובהוק חדש", + "no-webhook": "אין כרגע וובהוקים מוגדרים עבור שרת זה. כדי להתחיל, לחץ.", "run": "הרץ Webhook לבדיקה", "send_command": "פקודת שרת התקבלה", "start_server": "השרת הופעל", From 6e776d638330a588b938585172b6d6721e2e7e1a Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 12:15:00 -0500 Subject: [PATCH 36/84] Allow http to be disabled by config.json --- app/classes/web/tornado_handler.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/classes/web/tornado_handler.py b/app/classes/web/tornado_handler.py index f5501d31..82ae081c 100644 --- a/app/classes/web/tornado_handler.py +++ b/app/classes/web/tornado_handler.py @@ -112,7 +112,7 @@ class Webserver: cookie_secret = self.helper.random_string_generator(32) HelpersManagement.set_cookie_secret(cookie_secret) - if not http_port: + if not http_port and http_port != 0: http_port = 8000 if not https_port: @@ -190,9 +190,12 @@ class Webserver: login_url="/login", serve_traceback=debug_errors, ) - - self.http_server = tornado.httpserver.HTTPServer(http_app) - self.http_server.listen(http_port) + print(http_port) + if http_port != 0: + self.http_server = tornado.httpserver.HTTPServer(http_app) + self.http_server.listen(http_port) + else: + logger.info("http port disabled by config") self.https_server = tornado.httpserver.HTTPServer(app, ssl_options=cert_objects) self.https_server.listen(https_port) From 0fa7b592cc789912271535bbe23dcdf4ad39fa3b Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 12:58:02 -0500 Subject: [PATCH 37/84] Burn retinas - add warning banner Make warning system more robust --- app/frontend/templates/base.html | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index 48c6ee95..546502a2 100755 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -1,5 +1,5 @@ - + @@ -256,8 +256,9 @@ const sendWssError = () => wsOpen || warn( 'WebSockets are required for Crafty to work. This websocket connection has been closed. Are you using a reverse proxy?', - 'https://docs.craftycontrol.com/pages/getting-started/proxies/', - 'wssError' + link='https://docs.craftycontrol.com/pages/getting-started/proxies/', + link_msg="See our documentation for details", + className='wssError' ) function startWebSocket() { @@ -459,7 +460,7 @@ } - function warn(message, link = null, className = null) { + function warn(message, link = null, link_msg=null, className = null, bg_color="#f7970f") { var closeEl = document.createElement('span'); var strongEL = document.createElement('strong'); var msgEl = document.createElement('div'); @@ -481,14 +482,14 @@ var parentEl = document.createElement('div'); parentEl.style.padding = '20px'; - parentEl.style.backgroundColor = '#f7970f'; + parentEl.style.backgroundColor = bg_color; parentEl.appendChild(closeEl); parentEl.appendChild(msgEl); if (link) { let linkEl = document.createElement('a') linkEl.href = link; - linkEl.innerHTML = "See our documentation for details."; + linkEl.innerHTML = link_msg; linkEl.style.color = 'white'; linkEl.style.textDecoration = 'underline'; linkEl.target = "_blank"; @@ -580,6 +581,15 @@ $(document).ready(function () { console.log('%c[Crafty Controller] %cReady for JS!', 'font-weight: 900; color: #800080;', 'font-weight: 900; color: #eee;'); + if ($(document.documentElement).data("username") === "anti-lockout-user"){ + warn( + '⚠️You are in a recovery account. Access is limited!', + link='/logout', + link_msg="Click here to log out after you change your password. ⚠️", + className='anti-lockout', + bg_color='#2090d6' + ) + } $('#support_logs').click(function () { var dialog = bootbox.dialog({ message: "

{{ translate('notify', 'preparingLogs', data['lang']) }}

", From 854a9643e5fa176c4b8f32c991df402404c5d1b7 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 12:58:18 -0500 Subject: [PATCH 38/84] Fix bug where panel_config would always be loaded --- app/classes/web/panel_handler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 52d85acf..3cc276f2 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -285,8 +285,8 @@ class PanelHandler(BaseHandler): "Could not capture time zone from system. Falling back to Europe/London" ) tz = "Europe/London" - - page = "panel_config" + if exec_user["username"] == "anti-lockout-user": + page = "panel_config" page_data: t.Dict[str, t.Any] = { # todo: make this actually pull and compare version data From 5422915335a7b3a1d5019f203377b3199385825b Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 13:44:44 -0500 Subject: [PATCH 39/84] Delete user on logout --- app/classes/web/public_handler.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/classes/web/public_handler.py b/app/classes/web/public_handler.py index 57e6ddd8..7df88f68 100644 --- a/app/classes/web/public_handler.py +++ b/app/classes/web/public_handler.py @@ -61,7 +61,11 @@ class PublicHandler(BaseHandler): template = "public/offline.html" elif page == "logout": + exec_user = self.get_current_user() self.clear_cookie("token") + # Delete anti-lockout-user on lockout...it's one time use + if exec_user[2]["username"] == "anti-lockout-user": + self.controller.users.stop_anti_lockout() # self.clear_cookie("user") # self.clear_cookie("user_data") self.redirect("/login") From c5917267822bad3e06c9a33cd1967d7fcb57c4d4 Mon Sep 17 00:00:00 2001 From: "Analicia A." Date: Sun, 28 Jan 2024 18:45:56 +0000 Subject: [PATCH 40/84] Update translation for 4.2.3 --- app/translations/th_TH.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index 3d2826ea..a833cf1c 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -327,7 +327,7 @@ "bePatientDeleteFiles": "โปรดอดทนรอในขณะที่เราลบเซิร์ฟเวอร์ของคุณออกจากแผง Crafty และลบไฟล์ทั้งหมด หน้าต่องนี้จะปิดลงในอีกสักครู่", "bePatientUpdate": "กรุณารออย่างใจเย็นในขณะที่เราอัปเดตเซิร์ฟเวอร์ เวลาในการดาวน์โหลดอาจแตกต่างกันไปขึ้นอยู่กับความเร็วอินเทอร์เน็ตของคุณ
หน้าต่างนี้จะรีเฟรชในอีกสักครู่", "cancel": "ยกเลิก", - "countPlayers": "Include server in total player count", + "countPlayers": "รวมเซิร์ฟเวอร์ในจำนวนผู้เล่นทั้งหมด", "crashTime": "ผิดพลาด หมดเวลา", "crashTimeDesc": "เราควรรอนานแค่ไหนก่อนที่จะพิจารณาว่าเซิร์ฟเวอร์ของคุณขัดข้อง?", "deleteFilesQuestion": "ลบไฟล์เซิร์ฟเวอร์ออกจากเครื่อง?", From e399d57f475507a52c9a28fe85a85e571ea4d1d7 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 16:20:08 -0500 Subject: [PATCH 41/84] Fix no server id in audit log --- app/classes/web/routes/api/servers/server/stdin.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/web/routes/api/servers/server/stdin.py b/app/classes/web/routes/api/servers/server/stdin.py index 117fe188..ba8400b7 100644 --- a/app/classes/web/routes/api/servers/server/stdin.py +++ b/app/classes/web/routes/api/servers/server/stdin.py @@ -39,7 +39,7 @@ class ApiServersServerStdinHandler(BaseApiHandler): self.controller.management.add_to_audit_log( auth_data[4]["user_id"], f"Sent command ({decoded}) to terminal", - server_id=0, + server_id=server_id, source_ip=self.get_remote_ip(), ) if svr.send_command(self.request.body.decode("utf-8")): From 00ff98c99188ac5789de2fb7cdda54b4bdb0807a Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 16:20:58 -0500 Subject: [PATCH 42/84] Fix server term command send --- app/frontend/templates/panel/server_term.html | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/app/frontend/templates/panel/server_term.html b/app/frontend/templates/panel/server_term.html index bb63fbe7..a127e7aa 100644 --- a/app/frontend/templates/panel/server_term.html +++ b/app/frontend/templates/panel/server_term.html @@ -164,7 +164,7 @@ const serverId = new URLSearchParams(document.location.search).get('id') - function send_command(serverId, command) { + async function send_command(serverId, command) { if (command == 'start_server') { startBtn.setAttribute('disabled', 'disabled'); restartBtn.removeAttribute('disabled'); @@ -178,16 +178,23 @@ // const token = getCookie("_xsrf"); - $.ajax({ - type: "POST", - headers: { 'X-XSRFToken': token }, - url: `/api/v2/servers/${serverId}/action/${command}`, - success: function (data) { - console.log("got response:"); - console.log(data); - } + let res = await fetch(`/api/v2/servers/${serverId}/action/${command}`, { + method: 'POST', + headers: { + 'token': token, + }, }); + let responseData = await res.json(); + if (responseData.status === "ok") { + console.log("Command received successfully") + } else { + bootbox.alert({ + title: responseData.status, + message: responseData.error + }); + } } + if (webSocket) { webSocket.on('update_button_status', function (updateButton) { if (updateButton.isUpdating) { From ec5e291a98516844d3b88cf103706e6f7b5a01b6 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 16:21:27 -0500 Subject: [PATCH 43/84] Fix bug where del fail would give no feedback --- app/classes/shared/file_helpers.py | 7 ++++--- app/classes/web/routes/api/servers/server/files.py | 10 +++++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/app/classes/shared/file_helpers.py b/app/classes/shared/file_helpers.py index cc09dc4f..5e06c708 100644 --- a/app/classes/shared/file_helpers.py +++ b/app/classes/shared/file_helpers.py @@ -35,8 +35,9 @@ class FileHelpers: try: # This removes the top-level folder: path.rmdir() - except: + except Exception as e: logger.error("Unable to remove top level") + return e return True @staticmethod @@ -47,9 +48,9 @@ class FileHelpers: # Remove the file os.remove(path) return True - except FileNotFoundError: + except (FileNotFoundError, PermissionError) as e: logger.error(f"Path specified is not a file or does not exist. {path}") - return False + return e @staticmethod def copy_dir(src_path, dest_path, dirs_exist_ok=False): diff --git a/app/classes/web/routes/api/servers/server/files.py b/app/classes/web/routes/api/servers/server/files.py index 37007acd..8e70d4fe 100644 --- a/app/classes/web/routes/api/servers/server/files.py +++ b/app/classes/web/routes/api/servers/server/files.py @@ -237,10 +237,14 @@ class ApiServersServerFilesIndexHandler(BaseApiHandler): ) if os.path.isdir(data["filename"]): - FileHelpers.del_dirs(data["filename"]) + proc = FileHelpers.del_dirs(data["filename"]) else: - FileHelpers.del_file(data["filename"]) - return self.finish_json(200, {"status": "ok"}) + proc = FileHelpers.del_file(data["filename"]) + # disabling pylint because return value could be truthy + # but not a true boolean value + if proc == True: # pylint: disable=singleton-comparison + return self.finish_json(200, {"status": "ok"}) + return self.finish_json(500, {"status": "error", "error": str(proc)}) def patch(self, server_id: str): auth_data = self.authenticate_user() From a112bc3e579ca6d0dab2d20bb5d722f613597534 Mon Sep 17 00:00:00 2001 From: Andrew Date: Sun, 28 Jan 2024 16:51:54 -0500 Subject: [PATCH 44/84] Set time to UTC for schedule remove prints --- app/classes/controllers/users_controller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/classes/controllers/users_controller.py b/app/classes/controllers/users_controller.py index 80a431bf..c478f887 100644 --- a/app/classes/controllers/users_controller.py +++ b/app/classes/controllers/users_controller.py @@ -2,6 +2,7 @@ import logging import typing as t import datetime from datetime import timedelta +from zoneinfo import ZoneInfo from apscheduler.schedulers.background import BackgroundScheduler from app.classes.models.servers import HelperServers @@ -387,10 +388,9 @@ class UsersController: self.stop_anti_lockout, "date", id="anti-lockout-watcher", - run_date=datetime.datetime.now() + timedelta(hours=1), + run_date=datetime.datetime.now(ZoneInfo("Etc/UTC")) + timedelta(hours=1), ) def stop_anti_lockout(self): - print("IN STOP") self.scheduler.remove_all_jobs() self.users_helper.remove_user(self.get_id_by_name("anti-lockout-user")) From 02fbc5056d09ebfed408e790e6b9e2e47b2b70c3 Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 17:15:20 -0500 Subject: [PATCH 45/84] Redirect 404 on non-existant page --- app/classes/web/panel_handler.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 868bd5a3..02a5dbc1 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -28,6 +28,7 @@ from app.classes.web.base_handler import BaseHandler from app.classes.web.webhooks.webhook_factory import WebhookFactory logger = logging.getLogger(__name__) +# You must put any new subpages in here SUBPAGE_PERMS = { "term": EnumPermissionsServer.TERMINAL, "logs": EnumPermissionsServer.LOGS, @@ -625,6 +626,14 @@ class PanelHandler(BaseHandler): # have no perms if not subpage: self.redirect("/panel/error?error=Unauthorized access to Server") + if subpage not in SUBPAGE_PERMS.keys(): + self.set_status(404) + page_data["background"] = self.controller.cached_login + return self.render( + "public/404.html", + data=page_data, + translate=self.translator.translate, + ) page_data["active_link"] = subpage logger.debug(f'Subpage: "{subpage}"') From 06f59110fe308cdc1b7e646029ced3ab23b6097f Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 17:57:05 -0500 Subject: [PATCH 46/84] Add warning to wizard for unsupported mc --- app/frontend/templates/server/wizard.html | 17 ++++++++++++++++- app/translations/en_EN.json | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/app/frontend/templates/server/wizard.html b/app/frontend/templates/server/wizard.html index bb5fc175..6187088c 100644 --- a/app/frontend/templates/server/wizard.html +++ b/app/frontend/templates/server/wizard.html @@ -107,7 +107,8 @@
- +
@@ -1233,6 +1234,20 @@ } }) } + $("#server").change(function (){ + console.log(); + if($("#server :selected").text().split(".")[1] === "7"){ + $('[data-toggle="popover"]').popover(); + if ($(window).width() < 1000) { + $('.version-hint').attr("data-placement", "top") + } else { + $('.version-hint').attr("data-placement", "right") + } + $('.version-hint').popover("show"); + }else{ + $('.version-hint').popover("hide"); + } + }); function serverJarChange(selectObj) { const type_select = document.getElementById('server_jar') diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index a717c929..df26b13d 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -578,6 +578,7 @@ "serverUpload": "Upload Zipped Server", "serverVersion": "Server Version", "sizeInGB": "Size in GB", + "unsupported": "Minecraft versions lower than 1.8 are not supported by Crafty. You may still install it. Results will vary.", "uploadButton": "Upload", "uploadZip": "Upload Zip File For Server Import", "zipPath": "Server Path" From 476515bab0cde04cad81d775228994a25e15d2f6 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Sun, 28 Jan 2024 22:59:09 +0000 Subject: [PATCH 47/84] Update changelog !696 --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35257c29..e3595f2e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -12,7 +12,8 @@ - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) - Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) ### Lang -TBD +- Update `zh_CN, pl_PL, nl_BE, lv_LV, he_IL, fr_FR, de_DE, lol_EN` translations for `4.2.3` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/696)) +- New `uk_UA, tr_TR, th_TH` translations for `4.2.3` ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/696))

## --- [4.2.2] - 2023/12/13 From 71ab03c614f7a51a17157abde1cac8f6a80d358a Mon Sep 17 00:00:00 2001 From: Zedifus Date: Sun, 28 Jan 2024 23:11:47 +0000 Subject: [PATCH 48/84] Update changelog !695 --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35257c29..3645c9ba 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ ### New features - Use Papermc Group's API for `paper` & `folia` builds in server builder ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/688)) - Allow omission of player count from Dashboard (e.g. for proxy servers) ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/692)) +### Refactor +- Refactor subpage perm checks ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/695)) ### Bug fixes - Fix bukkit and downstream fork MOTD crash ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/686)) - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) From fb32f64a1319df7383a68d0cb3b94a711974f31f Mon Sep 17 00:00:00 2001 From: amcmanu3 Date: Sun, 28 Jan 2024 18:22:41 -0500 Subject: [PATCH 49/84] Improve logic just in case minecraft 2.0 --- app/frontend/templates/server/wizard.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/frontend/templates/server/wizard.html b/app/frontend/templates/server/wizard.html index 6187088c..2d84e6aa 100644 --- a/app/frontend/templates/server/wizard.html +++ b/app/frontend/templates/server/wizard.html @@ -1235,8 +1235,8 @@ }) } $("#server").change(function (){ - console.log(); - if($("#server :selected").text().split(".")[1] === "7"){ + let selected_version = $("#server :selected").text().split("."); + if(parseInt(selected_version[0]) === 1 && parseInt(selected_version[1]) < 8 ){ $('[data-toggle="popover"]').popover(); if ($(window).width() < 1000) { $('.version-hint').attr("data-placement", "top") From f684679225848a813946732fa9fda55a1b441213 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Sun, 28 Jan 2024 23:31:30 +0000 Subject: [PATCH 50/84] Update changelog !699 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index da73024f..ed3a2378 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ - Fix bug where invalid server Id leads to stack ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/690)) - Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) - Fix unicode chars in terminal & logs w/ textiowrapper ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/689)) +- Provide feedback on file delete failure ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/699)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) - Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) From 8a0cc2798f79dc0c7b407eb865783f93a4efbdb1 Mon Sep 17 00:00:00 2001 From: Zedifus Date: Sun, 28 Jan 2024 23:49:33 +0000 Subject: [PATCH 51/84] Update changelog !700 --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ed3a2378..2e2575fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,7 @@ - Fix indent on public status check box ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/691)) - Fix unicode chars in terminal & logs w/ textiowrapper ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/689)) - Provide feedback on file delete failure ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/699)) +- Fix bug where audit log would show 0 for any stdin sent to the server ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/700)) ### Tweaks - Refactor Forge server initialisation flow for newer versions ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/687)) - Remove scroll bars from player management ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/693)) From 7339181ce8fa1400dc91ce780465bc31e6bd6afa Mon Sep 17 00:00:00 2001 From: Iain Powrie Date: Mon, 29 Jan 2024 00:24:53 +0000 Subject: [PATCH 52/84] Retire Qube in offline credits --- app/config/credits.json | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/config/credits.json b/app/config/credits.json index fac21fdb..9b21e4e7 100644 --- a/app/config/credits.json +++ b/app/config/credits.json @@ -120,6 +120,20 @@ "blurb": "Silver enjoys helping others with their computer needs, writing documentation, and loving her cat.", "pic": "/static/assets/images/credits/isilverfyre.png" }, + { + "name": "Kornster", + "title": null, + "loc": "Victoria, Australia", + "tags": [ + "Discord Mod", + null, + null + ], + "blurb": "Day to day I am a Network Administrator, dealing with a range of vendors and products. Outside of work my hobbies are handyman things, such as carpentry and motor mechanics having grown up around them. My home-lab consists of Linux distros ranging from Debian, Ubuntu & Centos having self taught myself Linux for the last 12+ years.", + "pic": null + } + ], + "retired": [ { "name": "Quentin", "title": "Document Curator", @@ -135,20 +149,6 @@ "blurb": "Hosts Minecraft servers for his weird friends, works for an IoT company as his dayjob. The 's' in IoT stands for 'secure'.", "pic": "/static/assets/images/credits/qub3d.png" }, - { - "name": "Kornster", - "title": null, - "loc": "Victoria, Australia", - "tags": [ - "Discord Mod", - null, - null - ], - "blurb": "Day to day I am a Network Administrator, dealing with a range of vendors and products. Outside of work my hobbies are handyman things, such as carpentry and motor mechanics having grown up around them. My home-lab consists of Linux distros ranging from Debian, Ubuntu & Centos having self taught myself Linux for the last 12+ years.", - "pic": null - } - ], - "retired": [ { "name": "Kev Dagoat", "title": "Head of Development", From 522be7e4dc3ae552fce75dfd368a458906941648 Mon Sep 17 00:00:00 2001 From: Iain Powrie Date: Mon, 29 Jan 2024 01:02:27 +0000 Subject: [PATCH 53/84] Retire Kornster in offline credits --- app/config/credits.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/app/config/credits.json b/app/config/credits.json index 9b21e4e7..17996cf1 100644 --- a/app/config/credits.json +++ b/app/config/credits.json @@ -119,18 +119,6 @@ ], "blurb": "Silver enjoys helping others with their computer needs, writing documentation, and loving her cat.", "pic": "/static/assets/images/credits/isilverfyre.png" - }, - { - "name": "Kornster", - "title": null, - "loc": "Victoria, Australia", - "tags": [ - "Discord Mod", - null, - null - ], - "blurb": "Day to day I am a Network Administrator, dealing with a range of vendors and products. Outside of work my hobbies are handyman things, such as carpentry and motor mechanics having grown up around them. My home-lab consists of Linux distros ranging from Debian, Ubuntu & Centos having self taught myself Linux for the last 12+ years.", - "pic": null } ], "retired": [ @@ -149,6 +137,18 @@ "blurb": "Hosts Minecraft servers for his weird friends, works for an IoT company as his dayjob. The 's' in IoT stands for 'secure'.", "pic": "/static/assets/images/credits/qub3d.png" }, + { + "name": "Kornster", + "title": null, + "loc": "Victoria, Australia", + "tags": [ + "Discord Mod", + null, + null + ], + "blurb": "Day to day I am a Network Administrator, dealing with a range of vendors and products. Outside of work my hobbies are handyman things, such as carpentry and motor mechanics having grown up around them. My home-lab consists of Linux distros ranging from Debian, Ubuntu & Centos having self taught myself Linux for the last 12+ years.", + "pic": null + }, { "name": "Kev Dagoat", "title": "Head of Development", From e48a3cc9761f4e5313b158a689e08950602ae216 Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Tue, 30 Jan 2024 22:03:58 +0100 Subject: [PATCH 54/84] Improving Display for Buttons --- app/frontend/static/assets/css/crafty.css | 486 +++++++++++++++++++++- 1 file changed, 481 insertions(+), 5 deletions(-) diff --git a/app/frontend/static/assets/css/crafty.css b/app/frontend/static/assets/css/crafty.css index cc1a8b82..55efaeb6 100644 --- a/app/frontend/static/assets/css/crafty.css +++ b/app/frontend/static/assets/css/crafty.css @@ -37,16 +37,16 @@ nav.sidebar { width: 10px; height: 10px; border-radius: 100%; - border: 2px solid #fff; + border: 2px solid var(--white); display: block; } .toggle-handle { - background-color: white !important; + background-color: var(--white) !important; } .toggle-on { - color: black !important; + color: var(--dark) !important; } .toggle { @@ -61,7 +61,7 @@ nav.sidebar { width: 10px; height: 10px; border-radius: 100%; - border: 2px solid #fff; + border: 2px solid var(--white); display: block; } @@ -95,7 +95,7 @@ nav.sidebar { } .scrollable-element { - scrollbar-color: red yellow; + scrollbar-color: var(--red) var(--yellow); } .term-nav-item { @@ -140,6 +140,454 @@ body { text-align: center; } +/**************************************************************/ +/* CSS for Toggle Buttons */ +/**************************************************************/ +.btn-toggle { + margin: 0 4rem; + padding: 0; + position: relative; + border: none; + height: 1.5rem; + width: 3rem; + border-radius: 1.5rem; + color: #6b7381; + background: #bdc1c8; +} + +.btn-toggle:focus, +.btn-toggle.focus, +.btn-toggle:focus.active, +.btn-toggle.focus.active { + outline: none; +} + +.btn-toggle:before, +.btn-toggle:after { + line-height: 1.5rem; + width: 4rem; + text-align: center; + font-weight: 600; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 2px; + position: absolute; + bottom: 0; + transition: opacity 0.25s; +} + +.btn-toggle:before { + content: 'Off'; + left: -4rem; +} + +.btn-toggle:after { + content: 'On'; + right: -4rem; + opacity: 0.5; +} + +.btn-toggle>.handle { + position: absolute; + top: 0.1875rem; + left: 0.1875rem; + width: 1.125rem; + height: 1.125rem; + border-radius: 1.125rem; + background: var(--white); + transition: left 0.25s; +} + +.btn-toggle.active { + transition: background-color 0.25s; +} + +.btn-toggle.active>.handle { + left: 1.6875rem; + transition: left 0.25s; +} + +.btn-toggle.active:before { + opacity: 0.5; +} + +.btn-toggle.active:after { + opacity: 1; +} + +.btn-toggle.btn-sm:before, +.btn-toggle.btn-sm:after { + line-height: -0.5rem; + color: var(--white); + letter-spacing: 0.75px; + left: 0.4125rem; + width: 2.325rem; +} + +.btn-toggle.btn-sm:before { + text-align: right; +} + +.btn-toggle.btn-sm:after { + text-align: left; + opacity: 0; +} + +.btn-toggle.btn-sm.active:before { + opacity: 0; +} + +.btn-toggle.btn-sm.active:after { + opacity: 1; +} + +.btn-toggle.btn-xs:before, +.btn-toggle.btn-xs:after { + display: none; +} + +.btn-toggle:before, +.btn-toggle:after { + color: #6b7381; +} + +.btn-toggle.active { + background-color: #29b5a8; +} + +.btn-toggle.btn-lg { + margin: 0 5rem; + padding: 0; + position: relative; + border: none; + height: 2.5rem; + width: 5rem; + border-radius: 2.5rem; +} + +.btn-toggle.btn-lg:focus, +.btn-toggle.btn-lg.focus, +.btn-toggle.btn-lg:focus.active, +.btn-toggle.btn-lg.focus.active { + outline: none; +} + +.btn-toggle.btn-lg:before, +.btn-toggle.btn-lg:after { + line-height: 2.5rem; + width: 5rem; + text-align: center; + font-weight: 600; + font-size: 1rem; + text-transform: uppercase; + letter-spacing: 2px; + position: absolute; + bottom: 0; + transition: opacity 0.25s; +} + +.btn-toggle.btn-lg:before { + content: 'Off'; + left: -5rem; +} + +.btn-toggle.btn-lg:after { + content: 'On'; + right: -5rem; + opacity: 0.5; +} + +.btn-toggle.btn-lg>.handle { + position: absolute; + top: 0.3125rem; + left: 0.3125rem; + width: 1.875rem; + height: 1.875rem; + border-radius: 1.875rem; + background: var(--white); + transition: left 0.25s; +} + +.btn-toggle.btn-lg.active { + transition: background-color 0.25s; +} + +.btn-toggle.btn-lg.active>.handle { + left: 2.8125rem; + transition: left 0.25s; +} + +.btn-toggle.btn-lg.active:before { + opacity: 0.5; +} + +.btn-toggle.btn-lg.active:after { + opacity: 1; +} + +.btn-toggle.btn-lg.btn-sm:before, +.btn-toggle.btn-lg.btn-sm:after { + line-height: 0.5rem; + color: var(--white); + letter-spacing: 0.75px; + left: 0.6875rem; + width: 3.875rem; +} + +.btn-toggle.btn-lg.btn-sm:before { + text-align: right; +} + +.btn-toggle.btn-lg.btn-sm:after { + text-align: left; + opacity: 0; +} + +.btn-toggle.btn-lg.btn-sm.active:before { + opacity: 0; +} + +.btn-toggle.btn-lg.btn-sm.active:after { + opacity: 1; +} + +.btn-toggle.btn-lg.btn-xs:before, +.btn-toggle.btn-lg.btn-xs:after { + display: none; +} + +.btn-toggle.btn-sm { + margin: 0 0.5rem; + padding: 0; + position: relative; + border: none; + height: 1.5rem; + width: 3rem; + border-radius: 1.5rem; +} + +.btn-toggle.btn-sm:focus, +.btn-toggle.btn-sm.focus, +.btn-toggle.btn-sm:focus.active, +.btn-toggle.btn-sm.focus.active { + outline: none; +} + +.btn-toggle.btn-sm:before, +.btn-toggle.btn-sm:after { + line-height: 1.5rem; + width: 0.5rem; + text-align: center; + font-weight: 600; + font-size: 0.55rem; + text-transform: uppercase; + letter-spacing: 2px; + position: absolute; + bottom: 0; + transition: opacity 0.25s; +} + +.btn-toggle.btn-sm:before { + content: 'Off'; + left: -0.5rem; +} + +.btn-toggle.btn-sm:after { + content: 'On'; + right: -0.5rem; + opacity: 0.5; +} + +.btn-toggle.btn-sm>.handle { + position: absolute; + top: 0.1875rem; + left: 0.1875rem; + width: 1.125rem; + height: 1.125rem; + border-radius: 1.125rem; + background: var(--white); + transition: left 0.25s; +} + +.btn-toggle.btn-sm.active { + transition: background-color 0.25s; +} + +.btn-toggle.btn-sm.active>.handle { + left: 1.6875rem; + transition: left 0.25s; +} + +.btn-toggle.btn-sm.active:before { + opacity: 0.5; +} + +.btn-toggle.btn-sm.active:after { + opacity: 1; +} + +.btn-toggle.btn-sm.btn-sm:before, +.btn-toggle.btn-sm.btn-sm:after { + line-height: -0.5rem; + color: var(--white); + letter-spacing: 0.75px; + left: 0.4125rem; + width: 2.325rem; +} + +.btn-toggle.btn-sm.btn-sm:before { + text-align: right; +} + +.btn-toggle.btn-sm.btn-sm:after { + text-align: left; + opacity: 0; +} + +.btn-toggle.btn-sm.btn-sm.active:before { + opacity: 0; +} + +.btn-toggle.btn-sm.btn-sm.active:after { + opacity: 1; +} + +.btn-toggle.btn-sm.btn-xs:before, +.btn-toggle.btn-sm.btn-xs:after { + display: none; +} + +.btn-toggle.btn-xs { + margin: 0 0; + padding: 0; + position: relative; + border: none; + height: 1rem; + width: 2rem; + border-radius: 1rem; +} + +.btn-toggle.btn-xs:focus, +.btn-toggle.btn-xs.focus, +.btn-toggle.btn-xs:focus.active, +.btn-toggle.btn-xs.focus.active { + outline: none; +} + +.btn-toggle.btn-xs:before, +.btn-toggle.btn-xs:after { + line-height: 1rem; + width: 0; + text-align: center; + font-weight: 600; + font-size: 0.75rem; + text-transform: uppercase; + letter-spacing: 2px; + position: absolute; + bottom: 0; + transition: opacity 0.25s; +} + +.btn-toggle.btn-xs:before { + content: 'Off'; + left: 0; +} + +.btn-toggle.btn-xs:after { + content: 'On'; + right: 0; + opacity: 0.5; +} + +.btn-toggle.btn-xs>.handle { + position: absolute; + top: 0.125rem; + left: 0.125rem; + width: 0.75rem; + height: 0.75rem; + border-radius: 0.75rem; + background: var(--white); + transition: left 0.25s; +} + +.btn-toggle.btn-xs.active { + transition: background-color 0.25s; +} + +.btn-toggle.btn-xs.active>.handle { + left: 1.125rem; + transition: left 0.25s; +} + +.btn-toggle.btn-xs.active:before { + opacity: 0.5; +} + +.btn-toggle.btn-xs.active:after { + opacity: 1; +} + +.btn-toggle.btn-xs.btn-sm:before, +.btn-toggle.btn-xs.btn-sm:after { + line-height: -1rem; + color: var(--white); + letter-spacing: 0.75px; + left: 0.275rem; + width: 1.55rem; +} + +.btn-toggle.btn-xs.btn-sm:before { + text-align: right; +} + +.btn-toggle.btn-xs.btn-sm:after { + text-align: left; + opacity: 0; +} + +.btn-toggle.btn-xs.btn-sm.active:before { + opacity: 0; +} + +.btn-toggle.btn-xs.btn-sm.active:after { + opacity: 1; +} + +.btn-toggle.btn-xs.btn-xs:before, +.btn-toggle.btn-xs.btn-xs:after { + display: none; +} + +.btn-toggle.btn-info { + color: var(--white); + background: var(--gray); +} + +.btn-toggle.btn-info:before, +.btn-toggle.btn-info:after { + color: #6b7381; +} + +.btn-toggle.btn-info.active { + background-color: var(--info); +} + +.btn-toggle.btn-secondary { + color: #6b7381; + background: #bdc1c8; +} + +.btn-toggle.btn-secondary:before, +.btn-toggle.btn-secondary:after { + color: #6b7381; +} + +.btn-toggle.btn-secondary.active { + background-color: #ff8300; +} + +/**************************************************************/ + /**************************************************************/ /* CSS for Froms Displays */ /**************************************************************/ @@ -212,6 +660,14 @@ div>.input-group>.form-control { top: calc(-0.125rem + 1px); } +a.btn-primary { + color: var(--white); +} + +button.btn-primary { + color: var(--white); +} + /**************************************************************/ /**************************************************************/ @@ -233,4 +689,24 @@ td.action .btn { margin-bottom: 0.2rem; } +/**************************************************************/ + +/**************************************************************/ +/* CSS for warnings Displays */ +/**************************************************************/ +div.warnings div.wssError { + color: var(--white); +} + +div.warnings div.wssError a { + color: var(--white-smoke); +} + +/**************************************************************/ + +/**************************************************************/ +/* CSS for ----- Displays */ +/**************************************************************/ + + /**************************************************************/ \ No newline at end of file From 1c0190d0ab8c20aadb3210f20d54a6d47896e671 Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Tue, 30 Jan 2024 22:10:49 +0100 Subject: [PATCH 55/84] Impriove display for wssErrors --- app/frontend/static/assets/css/crafty.css | 452 +--------------------- app/frontend/templates/base.html | 6 +- 2 files changed, 7 insertions(+), 451 deletions(-) diff --git a/app/frontend/static/assets/css/crafty.css b/app/frontend/static/assets/css/crafty.css index 55efaeb6..4c55d7ae 100644 --- a/app/frontend/static/assets/css/crafty.css +++ b/app/frontend/static/assets/css/crafty.css @@ -140,454 +140,6 @@ body { text-align: center; } -/**************************************************************/ -/* CSS for Toggle Buttons */ -/**************************************************************/ -.btn-toggle { - margin: 0 4rem; - padding: 0; - position: relative; - border: none; - height: 1.5rem; - width: 3rem; - border-radius: 1.5rem; - color: #6b7381; - background: #bdc1c8; -} - -.btn-toggle:focus, -.btn-toggle.focus, -.btn-toggle:focus.active, -.btn-toggle.focus.active { - outline: none; -} - -.btn-toggle:before, -.btn-toggle:after { - line-height: 1.5rem; - width: 4rem; - text-align: center; - font-weight: 600; - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} - -.btn-toggle:before { - content: 'Off'; - left: -4rem; -} - -.btn-toggle:after { - content: 'On'; - right: -4rem; - opacity: 0.5; -} - -.btn-toggle>.handle { - position: absolute; - top: 0.1875rem; - left: 0.1875rem; - width: 1.125rem; - height: 1.125rem; - border-radius: 1.125rem; - background: var(--white); - transition: left 0.25s; -} - -.btn-toggle.active { - transition: background-color 0.25s; -} - -.btn-toggle.active>.handle { - left: 1.6875rem; - transition: left 0.25s; -} - -.btn-toggle.active:before { - opacity: 0.5; -} - -.btn-toggle.active:after { - opacity: 1; -} - -.btn-toggle.btn-sm:before, -.btn-toggle.btn-sm:after { - line-height: -0.5rem; - color: var(--white); - letter-spacing: 0.75px; - left: 0.4125rem; - width: 2.325rem; -} - -.btn-toggle.btn-sm:before { - text-align: right; -} - -.btn-toggle.btn-sm:after { - text-align: left; - opacity: 0; -} - -.btn-toggle.btn-sm.active:before { - opacity: 0; -} - -.btn-toggle.btn-sm.active:after { - opacity: 1; -} - -.btn-toggle.btn-xs:before, -.btn-toggle.btn-xs:after { - display: none; -} - -.btn-toggle:before, -.btn-toggle:after { - color: #6b7381; -} - -.btn-toggle.active { - background-color: #29b5a8; -} - -.btn-toggle.btn-lg { - margin: 0 5rem; - padding: 0; - position: relative; - border: none; - height: 2.5rem; - width: 5rem; - border-radius: 2.5rem; -} - -.btn-toggle.btn-lg:focus, -.btn-toggle.btn-lg.focus, -.btn-toggle.btn-lg:focus.active, -.btn-toggle.btn-lg.focus.active { - outline: none; -} - -.btn-toggle.btn-lg:before, -.btn-toggle.btn-lg:after { - line-height: 2.5rem; - width: 5rem; - text-align: center; - font-weight: 600; - font-size: 1rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} - -.btn-toggle.btn-lg:before { - content: 'Off'; - left: -5rem; -} - -.btn-toggle.btn-lg:after { - content: 'On'; - right: -5rem; - opacity: 0.5; -} - -.btn-toggle.btn-lg>.handle { - position: absolute; - top: 0.3125rem; - left: 0.3125rem; - width: 1.875rem; - height: 1.875rem; - border-radius: 1.875rem; - background: var(--white); - transition: left 0.25s; -} - -.btn-toggle.btn-lg.active { - transition: background-color 0.25s; -} - -.btn-toggle.btn-lg.active>.handle { - left: 2.8125rem; - transition: left 0.25s; -} - -.btn-toggle.btn-lg.active:before { - opacity: 0.5; -} - -.btn-toggle.btn-lg.active:after { - opacity: 1; -} - -.btn-toggle.btn-lg.btn-sm:before, -.btn-toggle.btn-lg.btn-sm:after { - line-height: 0.5rem; - color: var(--white); - letter-spacing: 0.75px; - left: 0.6875rem; - width: 3.875rem; -} - -.btn-toggle.btn-lg.btn-sm:before { - text-align: right; -} - -.btn-toggle.btn-lg.btn-sm:after { - text-align: left; - opacity: 0; -} - -.btn-toggle.btn-lg.btn-sm.active:before { - opacity: 0; -} - -.btn-toggle.btn-lg.btn-sm.active:after { - opacity: 1; -} - -.btn-toggle.btn-lg.btn-xs:before, -.btn-toggle.btn-lg.btn-xs:after { - display: none; -} - -.btn-toggle.btn-sm { - margin: 0 0.5rem; - padding: 0; - position: relative; - border: none; - height: 1.5rem; - width: 3rem; - border-radius: 1.5rem; -} - -.btn-toggle.btn-sm:focus, -.btn-toggle.btn-sm.focus, -.btn-toggle.btn-sm:focus.active, -.btn-toggle.btn-sm.focus.active { - outline: none; -} - -.btn-toggle.btn-sm:before, -.btn-toggle.btn-sm:after { - line-height: 1.5rem; - width: 0.5rem; - text-align: center; - font-weight: 600; - font-size: 0.55rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} - -.btn-toggle.btn-sm:before { - content: 'Off'; - left: -0.5rem; -} - -.btn-toggle.btn-sm:after { - content: 'On'; - right: -0.5rem; - opacity: 0.5; -} - -.btn-toggle.btn-sm>.handle { - position: absolute; - top: 0.1875rem; - left: 0.1875rem; - width: 1.125rem; - height: 1.125rem; - border-radius: 1.125rem; - background: var(--white); - transition: left 0.25s; -} - -.btn-toggle.btn-sm.active { - transition: background-color 0.25s; -} - -.btn-toggle.btn-sm.active>.handle { - left: 1.6875rem; - transition: left 0.25s; -} - -.btn-toggle.btn-sm.active:before { - opacity: 0.5; -} - -.btn-toggle.btn-sm.active:after { - opacity: 1; -} - -.btn-toggle.btn-sm.btn-sm:before, -.btn-toggle.btn-sm.btn-sm:after { - line-height: -0.5rem; - color: var(--white); - letter-spacing: 0.75px; - left: 0.4125rem; - width: 2.325rem; -} - -.btn-toggle.btn-sm.btn-sm:before { - text-align: right; -} - -.btn-toggle.btn-sm.btn-sm:after { - text-align: left; - opacity: 0; -} - -.btn-toggle.btn-sm.btn-sm.active:before { - opacity: 0; -} - -.btn-toggle.btn-sm.btn-sm.active:after { - opacity: 1; -} - -.btn-toggle.btn-sm.btn-xs:before, -.btn-toggle.btn-sm.btn-xs:after { - display: none; -} - -.btn-toggle.btn-xs { - margin: 0 0; - padding: 0; - position: relative; - border: none; - height: 1rem; - width: 2rem; - border-radius: 1rem; -} - -.btn-toggle.btn-xs:focus, -.btn-toggle.btn-xs.focus, -.btn-toggle.btn-xs:focus.active, -.btn-toggle.btn-xs.focus.active { - outline: none; -} - -.btn-toggle.btn-xs:before, -.btn-toggle.btn-xs:after { - line-height: 1rem; - width: 0; - text-align: center; - font-weight: 600; - font-size: 0.75rem; - text-transform: uppercase; - letter-spacing: 2px; - position: absolute; - bottom: 0; - transition: opacity 0.25s; -} - -.btn-toggle.btn-xs:before { - content: 'Off'; - left: 0; -} - -.btn-toggle.btn-xs:after { - content: 'On'; - right: 0; - opacity: 0.5; -} - -.btn-toggle.btn-xs>.handle { - position: absolute; - top: 0.125rem; - left: 0.125rem; - width: 0.75rem; - height: 0.75rem; - border-radius: 0.75rem; - background: var(--white); - transition: left 0.25s; -} - -.btn-toggle.btn-xs.active { - transition: background-color 0.25s; -} - -.btn-toggle.btn-xs.active>.handle { - left: 1.125rem; - transition: left 0.25s; -} - -.btn-toggle.btn-xs.active:before { - opacity: 0.5; -} - -.btn-toggle.btn-xs.active:after { - opacity: 1; -} - -.btn-toggle.btn-xs.btn-sm:before, -.btn-toggle.btn-xs.btn-sm:after { - line-height: -1rem; - color: var(--white); - letter-spacing: 0.75px; - left: 0.275rem; - width: 1.55rem; -} - -.btn-toggle.btn-xs.btn-sm:before { - text-align: right; -} - -.btn-toggle.btn-xs.btn-sm:after { - text-align: left; - opacity: 0; -} - -.btn-toggle.btn-xs.btn-sm.active:before { - opacity: 0; -} - -.btn-toggle.btn-xs.btn-sm.active:after { - opacity: 1; -} - -.btn-toggle.btn-xs.btn-xs:before, -.btn-toggle.btn-xs.btn-xs:after { - display: none; -} - -.btn-toggle.btn-info { - color: var(--white); - background: var(--gray); -} - -.btn-toggle.btn-info:before, -.btn-toggle.btn-info:after { - color: #6b7381; -} - -.btn-toggle.btn-info.active { - background-color: var(--info); -} - -.btn-toggle.btn-secondary { - color: #6b7381; - background: #bdc1c8; -} - -.btn-toggle.btn-secondary:before, -.btn-toggle.btn-secondary:after { - color: #6b7381; -} - -.btn-toggle.btn-secondary.active { - background-color: #ff8300; -} - -/**************************************************************/ - /**************************************************************/ /* CSS for Froms Displays */ /**************************************************************/ @@ -699,6 +251,10 @@ div.warnings div.wssError { } div.warnings div.wssError a { + color: var(--outline); +} + +div.warnings div.wssError a:hover { color: var(--white-smoke); } diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index 48c6ee95..9f1a4111 100755 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -394,7 +394,7 @@ } }, callback: function (result) { - if (result){ + if (result) { location.href = "/panel/download_support_package"; } else { bootbox.close(); @@ -489,7 +489,7 @@ let linkEl = document.createElement('a') linkEl.href = link; linkEl.innerHTML = "See our documentation for details."; - linkEl.style.color = 'white'; + //linkEl.style.color = 'white'; linkEl.style.textDecoration = 'underline'; linkEl.target = "_blank"; @@ -608,4 +608,4 @@ - + \ No newline at end of file From 856caf4a9a71ac2c87b47538bb74e1c155998dce Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Tue, 30 Jan 2024 22:44:00 +0100 Subject: [PATCH 56/84] trying to improve display for th-TH lang --- app/frontend/static/assets/css/crafty.css | 6 +++++- app/frontend/templates/base.html | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/frontend/static/assets/css/crafty.css b/app/frontend/static/assets/css/crafty.css index 4c55d7ae..1bf03471 100644 --- a/app/frontend/static/assets/css/crafty.css +++ b/app/frontend/static/assets/css/crafty.css @@ -261,8 +261,12 @@ div.warnings div.wssError a:hover { /**************************************************************/ /**************************************************************/ -/* CSS for ----- Displays */ +/* CSS for Fonts Displays */ /**************************************************************/ +*:lang(th-TH) :not(.fas) { + font-family: 'Sarabun', 'roboto', sans-serif; + font-size: medium; +} /**************************************************************/ \ No newline at end of file diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index 9f1a4111..a954859f 100755 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -14,6 +14,7 @@ + @@ -53,7 +54,6 @@ - From 98bbf880d0e9dd8c65afefba96d1fc68a88d922d Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Tue, 30 Jan 2024 22:58:19 +0100 Subject: [PATCH 57/84] Fixing Fonts for th-TH --- app/frontend/static/assets/css/crafty.css | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/frontend/static/assets/css/crafty.css b/app/frontend/static/assets/css/crafty.css index 1bf03471..286155ab 100644 --- a/app/frontend/static/assets/css/crafty.css +++ b/app/frontend/static/assets/css/crafty.css @@ -263,10 +263,9 @@ div.warnings div.wssError a:hover { /**************************************************************/ /* CSS for Fonts Displays */ /**************************************************************/ -*:lang(th-TH) :not(.fas) { +*:lang(th-TH) :not(.fa, .fas, .fab, .fa-solid) { font-family: 'Sarabun', 'roboto', sans-serif; font-size: medium; } - /**************************************************************/ \ No newline at end of file From a26159f510d42308fd405f06c031bb1dfa32ca55 Mon Sep 17 00:00:00 2001 From: computergeek125 Date: Wed, 31 Jan 2024 01:33:39 -0600 Subject: [PATCH 58/84] Added timeout to http calls, switched get to head --- app/classes/web/http_handler.py | 4 ++-- app/classes/web/http_handler_page.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/classes/web/http_handler.py b/app/classes/web/http_handler.py index ca340c66..32676d59 100644 --- a/app/classes/web/http_handler.py +++ b/app/classes/web/http_handler.py @@ -17,7 +17,7 @@ class HTTPHandler(BaseHandler): url = "https://" + url db_port = self.helper.get_setting("https_port") try: - resp = requests.get(url + ":" + str(port)) + resp = requests.head(url + ":" + str(port), timeout=(0.5, 5)) resp.raise_for_status() except Exception: port = db_port @@ -35,7 +35,7 @@ class HTTPHandlerPage(BaseHandler): url = "https://" + url db_port = self.helper.get_setting("https_port") try: - resp = requests.get(url + ":" + str(port)) + resp = requests.head(url + ":" + str(port), timeout=(0.5, 5)) resp.raise_for_status() except Exception: port = db_port diff --git a/app/classes/web/http_handler_page.py b/app/classes/web/http_handler_page.py index 30a8aaa1..77161577 100644 --- a/app/classes/web/http_handler_page.py +++ b/app/classes/web/http_handler_page.py @@ -25,7 +25,7 @@ class HTTPHandlerPage(BaseHandler): backup_url = url + str(self.helper.get_setting("https_port")) try: - resp = requests.get(primary_url) + resp = requests.head(primary_url, timeout=(0.5, 5)) resp.raise_for_status() url = primary_url except Exception: From d92d06e4b1b51701dd7167a34c4d36e9d1f08b47 Mon Sep 17 00:00:00 2001 From: Silversthorn Date: Wed, 31 Jan 2024 23:04:22 +0100 Subject: [PATCH 59/84] Fixing issue 322 --- app/frontend/static/assets/js/motd.js | 2 +- app/frontend/templates/panel/dashboard.html | 38 +++--- .../templates/panel/parts/details_stats.html | 120 ++++++++---------- app/frontend/templates/public/status.html | 5 +- app/translations/en_EN.json | 3 +- app/translations/fr_FR.json | 3 +- 6 files changed, 76 insertions(+), 95 deletions(-) diff --git a/app/frontend/static/assets/js/motd.js b/app/frontend/static/assets/js/motd.js index 3d07c8fb..8f63e763 100644 --- a/app/frontend/static/assets/js/motd.js +++ b/app/frontend/static/assets/js/motd.js @@ -96,7 +96,7 @@ function initParser(input, output) { var input = document.getElementById(input), output = document.getElementById(output); if (input != null && output != null) { - var parsed = parseStyle(input.innerHTML); + var parsed = parseStyle(input.innerText); output.innerHTML = ''; output.appendChild(parsed); } diff --git a/app/frontend/templates/panel/dashboard.html b/app/frontend/templates/panel/dashboard.html index eb4a51a9..0d4fc0ac 100644 --- a/app/frontend/templates/panel/dashboard.html +++ b/app/frontend/templates/panel/dashboard.html @@ -287,8 +287,7 @@ data['lang']) }}
{% if server['stats']['desc'] != 'False' %} -
{{ - server['stats']['desc'] }}

+
{{ translate('serverStats', 'loadingMotd', data['lang']) }}

{% end %} {% if server['stats']['version'] != 'False' %} @@ -554,6 +553,7 @@ display: none; /* for Chrome, Safari, and Opera */ } + .gray { color: gray !important; } @@ -736,11 +736,11 @@ try { console.log(`#server_desc_${server.getAttribute("data-serverId")}`) $(`#server_desc_${server.getAttribute("data-serverId")}`).toggleClass("gray", server.getAttribute('data-count') === 'false') - if (server.getAttribute('data-count') === 'true'){ + if (server.getAttribute('data-count') === 'true') { all_total_players += parseInt(server.getAttribute('data-players')); all_total_max_players += parseInt(server.getAttribute('data-max')); } - } catch { + } catch { console.log("Player totals are not of type int"); } }) @@ -1006,24 +1006,24 @@ async function sendOrder(id_string) { const token = getCookie("_xsrf") let res = await fetch(`/api/v2/users/@me`, { - method: 'PATCH', - headers: { - 'X-XSRFToken': token - }, - body: JSON.stringify({ + method: 'PATCH', + headers: { + 'X-XSRFToken': token + }, + body: JSON.stringify({ server_order: id_string, }), - }); - let responseData = await res.json(); - if (responseData.status === "ok") { - return - } else { - - bootbox.alert({ - title: responseData.status, - message: responseData.error }); - } + let responseData = await res.json(); + if (responseData.status === "ok") { + return + } else { + + bootbox.alert({ + title: responseData.status, + message: responseData.error + }); + } } // Inits the sortable $("table#servers_table tbody") diff --git a/app/frontend/templates/panel/parts/details_stats.html b/app/frontend/templates/panel/parts/details_stats.html index ad190bc3..00fa516b 100644 --- a/app/frontend/templates/panel/parts/details_stats.html +++ b/app/frontend/templates/panel/parts/details_stats.html @@ -5,42 +5,27 @@
{% if data['server_stats']['running'] %} - {{ translate('serverStats', 'serverStatus', data['lang']) }}: {{ translate('serverStats', 'online', data['lang']) }}
- {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ - data['server_stats']['started'] }}
- {{ translate('serverStats', 'serverUptime', data['lang']) }}: {{ - translate('serverStats', 'errorCalculatingUptime', data['lang']) }} + {{ translate('serverStats', 'serverStatus', data['lang']) }}: {{ translate('serverStats', 'online', data['lang']) }}
+ {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ data['server_stats']['started'] }}
+ {{ translate('serverStats', 'serverUptime', data['lang']) }}: {{ translate('serverStats', 'errorCalculatingUptime', data['lang']) }} {% elif data['server_stats']['crashed'] %} - {{ translate('serverStats', 'serverStatus', data['lang']) }}: - {{ translate('dashboard', 'crashed', data['lang']) - }}
- {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ translate('dashboard', 'crashed', - data['lang']) }}
- {{ translate('serverStats', 'serverUptime', data['lang']) }}: - {{ translate('dashboard', 'crashed', data['lang']) }} + {{ translate('serverStats', 'serverStatus', data['lang']) }}: {{ translate('dashboard', 'crashed', data['lang']) }}
+ {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ translate('dashboard', 'crashed',data['lang']) }}
+ {{ translate('serverStats', 'serverUptime', data['lang']) }}: {{ translate('dashboard', 'crashed', data['lang']) }} {% else %} - {{ translate('serverStats', 'serverStatus', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }}
- {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }}
- {{ translate('serverStats', 'serverUptime', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }} + {{ translate('serverStats', 'serverStatus', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }}
+ {{ translate('serverStats', 'serverStarted', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }}
+ {{ translate('serverStats', 'serverUptime', data['lang']) }}: {{ translate('serverStats', 'offline', data['lang']) }} {% end %}
- {{ translate('serverStats', 'serverTimeZone', data['lang']) }}: {{ - data['serverTZ'] }} + {{ translate('serverStats', 'serverTimeZone', data['lang']) }}: {{ data['serverTZ'] }}
- {{ translate('serverStats', 'cpuUsage', data['lang']) }}: {{ - data['server_stats']['cpu'] }}%
- {{ translate('serverStats', 'memUsage', data['lang']) }}: {{ - data['server_stats']['mem'] }}
+ {{ translate('serverStats', 'cpuUsage', data['lang']) }}: {{ data['server_stats']['cpu'] }}%
+ {{ translate('serverStats', 'memUsage', data['lang']) }}: {{ data['server_stats']['mem'] }}
{% if data['server_stats']['int_ping_results'] %} - {{ translate('serverStats', 'players', data['lang']) }}: {{ - data['server_stats']['online'] }} / {{ data['server_stats']['max'] }}
+ {{ translate('serverStats', 'players', data['lang']) }}: {{ data['server_stats']['online'] }} / {{ data['server_stats']['max'] }}
{% else %} {{ translate('serverStats', 'players', data['lang']) }}: 0/0
{% end %} @@ -48,17 +33,12 @@
{% if data['server_stats']['version'] != 'False' %} - {{ translate('serverStats', 'version', data['lang']) }}: {{ - data['server_stats']['version'] }}
- {{ translate('serverStats', 'description', data['lang']) }}: {{ data['server_stats']['desc'] }} + {{ translate('serverStats', 'version', data['lang']) }}: {{ data['server_stats']['version'] }}
+ {{ translate('serverStats', 'description', data['lang']) }}: {{ translate('serverStats', 'loadingMotd', data['lang']) }}
{% else %} - {{ translate('serverStats', 'version', data['lang']) }}: {{ - translate('serverStats', 'unableToConnect', data['lang']) }}
- {{ translate('serverStats', 'description', data['lang']) }}: {{ translate('serverStats', - 'unableToConnect', data['lang']) }}
+ {{ translate('serverStats', 'version', data['lang']) }}: {{ translate('serverStats', 'unableToConnect', data['lang']) }}
+ {{ translate('serverStats', 'description', data['lang']) }}: {{ translate('serverStats', 'unableToConnect', data['lang']) }}
{% end %} Server Type: {{data['server_stats']['server_type']}} @@ -229,23 +209,23 @@ initParser('input_motd', 'input_motd'); let text = "" - let players = server.players_cache; - for(let i=0; i < players.length; i++){ - text += ``; - text += `${players[i]["name"]}`; - if(players[i]["status"] === "Online"){ - text += ` ${ players[i]['status'] }` - }else{ - text += ` ${ players[i]['status'] } Last connection :
${ players[i]['last_seen'] }
` - } - if(server["running"]){ - text += `


` - }else{ - text += ` Unavailable
(Server Offline)
` - } + let players = server.players_cache; + for (let i = 0; i < players.length; i++) { + text += ``; + text += `${players[i]["name"]}`; + if (players[i]["status"] === "Online") { + text += ` ${players[i]['status']}` + } else { + text += ` ${players[i]['status']} Last connection :
${players[i]['last_seen']}
` + } + if (server["running"]) { + text += `


` + } else { + text += ` Unavailable
(Server Offline)
` + } - } - $("#player-body").html(text); + } + $("#player-body").html(text); } //used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security @@ -262,24 +242,24 @@ add_server_name(); //} }); - async function add_server_name(){ + async function add_server_name() { let res = await fetch(`/api/v2/servers/${serverId}`, { - method: 'GET', - headers: { - 'X-XSRFToken': token - }, - }); - let responseData = await res.json(); - if (responseData.status === "ok") { - console.log(responseData) - $("#server-name-nav").html(`${responseData.data['server_name']}`) - $("#server-name-nav").show(); - } else { + method: 'GET', + headers: { + 'X-XSRFToken': token + }, + }); + let responseData = await res.json(); + if (responseData.status === "ok") { + console.log(responseData) + $("#server-name-nav").html(`${responseData.data['server_name']}`) + $("#server-name-nav").show(); + } else { - bootbox.alert({ - title: responseData.error, - message: responseData.error_data - }); - } + bootbox.alert({ + title: responseData.error, + message: responseData.error_data + }); + } } \ No newline at end of file diff --git a/app/frontend/templates/public/status.html b/app/frontend/templates/public/status.html index 1190b9f8..0693ee2e 100644 --- a/app/frontend/templates/public/status.html +++ b/app/frontend/templates/public/status.html @@ -49,7 +49,7 @@ icon
- {{ server['stats']['desc'] }} + {{ translate('serverStats', 'loadingMotd', data['lang']) }}
{% end %} @@ -133,8 +133,7 @@
{% if server['stats']['desc'] != 'False' %}
- {{ - server['stats']['desc'] }}
+ {{ translate('serverStats', 'loadingMotd', data['lang']) }}
{% end %}
diff --git a/app/translations/en_EN.json b/app/translations/en_EN.json index 32721082..25c9096e 100644 --- a/app/translations/en_EN.json +++ b/app/translations/en_EN.json @@ -512,6 +512,7 @@ "cpuUsage": "CPU Usage", "description": "Description", "errorCalculatingUptime": "Error Calculating Uptime", + "loadingMotd": "Loading MOTD", "memUsage": "Memory Usage", "offline": "Offline", "online": "Online", @@ -666,4 +667,4 @@ "webhook_body": "Webhook Body", "webhooks": "Webhooks" } -} +} \ No newline at end of file diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index aa45a69b..b8078a84 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -512,6 +512,7 @@ "cpuUsage": "Utilisation CPU", "description": "Description", "errorCalculatingUptime": "Erreur de Calcul du Temps de Disponibilité", + "loadingMotd": "Chargement MOTD", "memUsage": "Utilisation Mémoire", "offline": "Hors Ligne", "online": "En Ligne", @@ -667,4 +668,4 @@ "webhook_body": "Corps du Webhook", "webhooks": "Webhooks" } -} +} \ No newline at end of file From ccf67002cd76bb95c1e4fede47a9d94b22ff243f Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 31 Jan 2024 19:17:13 -0500 Subject: [PATCH 60/84] Remove print statement --- app/classes/web/tornado_handler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/classes/web/tornado_handler.py b/app/classes/web/tornado_handler.py index 82ae081c..fbcf970f 100644 --- a/app/classes/web/tornado_handler.py +++ b/app/classes/web/tornado_handler.py @@ -190,7 +190,7 @@ class Webserver: login_url="/login", serve_traceback=debug_errors, ) - print(http_port) + if http_port != 0: self.http_server = tornado.httpserver.HTTPServer(http_app) self.http_server.listen(http_port) From 729f854a670c89a3396d3ddd7f8767e2d3104bf9 Mon Sep 17 00:00:00 2001 From: Analicia Abernathy Date: Wed, 31 Jan 2024 19:47:14 -0600 Subject: [PATCH 61/84] Added required translations for branch --- app/translations/de_DE.json | 1 + app/translations/fr_FR.json | 1 + app/translations/he_IL.json | 1 + app/translations/lol_EN.json | 1 + app/translations/lv_LV.json | 1 + app/translations/nl_BE.json | 1 + app/translations/pl_PL.json | 1 + app/translations/th_TH.json | 1 + app/translations/tr_TR.json | 1 + app/translations/uk_UA.json | 1 + app/translations/zh_CN.json | 1 + 11 files changed, 11 insertions(+) diff --git a/app/translations/de_DE.json b/app/translations/de_DE.json index 1a7f8995..22bf6a57 100644 --- a/app/translations/de_DE.json +++ b/app/translations/de_DE.json @@ -579,6 +579,7 @@ "serverUpload": "Als Zip-Datei Gepackten Server hochladen", "serverVersion": "Server Version", "sizeInGB": "Größe in GB", + "unsupported": "Minecraft-Versionen vor 1.8 sind nicht vollständig auf Kompatibilität getestet. Bei einer Installation verhalten diese sich möglicherweise nicht wie erwartet.", "uploadButton": "Hochladen", "uploadZip": "Zip-Datei für Serverimport hochladen", "zipPath": "Server Pfad" diff --git a/app/translations/fr_FR.json b/app/translations/fr_FR.json index aa45a69b..4a0b88b1 100644 --- a/app/translations/fr_FR.json +++ b/app/translations/fr_FR.json @@ -579,6 +579,7 @@ "serverUpload": "Charger le fichier Zippé", "serverVersion": "Version du Serveur", "sizeInGB": "Taille en GB", + "unsupported": "Les versions Minecraft inférieures à 1.8 ne sont pas supportées par Crafty. Elles peuvent être installées, mais leur fonctionnement peut varier.", "uploadButton": "Chargement", "uploadZip": "Charger le fichier pour l'importation du Serveur", "zipPath": "Chemin du Serveur" diff --git a/app/translations/he_IL.json b/app/translations/he_IL.json index cff35559..3b6fa3ec 100644 --- a/app/translations/he_IL.json +++ b/app/translations/he_IL.json @@ -579,6 +579,7 @@ "serverUpload": "העלה שרת מכווץ", "serverVersion": "גרסת השרת", "sizeInGB": "גודל ב-GB", + "unsupported": "גרסאות מיינקראפט מתחת ל1.8 לא נתמכות על ידי קראפטי. אפשר להתקין אותם אבל הביצועים לא יהיו עקביים.", "uploadButton": "העלה", "uploadZip": "העלה קובץ Zip לייבוא שרת", "zipPath": "נתיב שרת" diff --git a/app/translations/lol_EN.json b/app/translations/lol_EN.json index 4836501b..8e51e4cb 100644 --- a/app/translations/lol_EN.json +++ b/app/translations/lol_EN.json @@ -579,6 +579,7 @@ "serverUpload": "UPLOADZ ZIPPED SERVR", "serverVersion": "SERVR VERZHUN", "sizeInGB": "SIEZ IN GIGABITEZ", + "unsupported": "MINECRAFTZ OLDR THAN 1.8 NOT FRENDS WIF CWAFTY. U CAN STILL TRY INSTALLIN'. IT MIGHT WORKS, MIGHT NOT.", "uploadButton": "UPLOADZ", "uploadZip": "UPLOADZ ZIP FISH FOR SERVR BRING IN", "zipPath": "WER IZ ZIP FISH (PETH)" diff --git a/app/translations/lv_LV.json b/app/translations/lv_LV.json index 354a0e54..09dec926 100644 --- a/app/translations/lv_LV.json +++ b/app/translations/lv_LV.json @@ -580,6 +580,7 @@ "serverUpload": "Augšupielādē Saspiestu (Zipotu) Serveri", "serverVersion": "Servera Versija", "sizeInGB": "lielums, GB", + "unsupported": "Minecraft versijas zem 1.8 netiek atbalstītas iekš Crafty. Jūs tāpat variet tās instalēt, bet rezultāti atškirsies.", "uploadButton": "Augšupielādēt", "uploadZip": "Augšupielādē Zip Failu Priekš Serveru Importa", "zipPath": "Servera Ceļš" diff --git a/app/translations/nl_BE.json b/app/translations/nl_BE.json index c9414bbe..f81f8bf5 100644 --- a/app/translations/nl_BE.json +++ b/app/translations/nl_BE.json @@ -579,6 +579,7 @@ "serverUpload": "Gezipt bestand uploaden", "serverVersion": "Serverversie", "sizeInGB": "Grootte in GB", + "unsupported": "Minecraft-versies lager dan 1.8 worden niet ondersteund door Crafty. Je kunt het nog steeds installeren. De resultaten kunnen variëren.", "uploadButton": "Uploaden", "uploadZip": "Upload zip-bestand voor serverimport", "zipPath": "Serverpad" diff --git a/app/translations/pl_PL.json b/app/translations/pl_PL.json index 86f8f9cb..e2a2d203 100644 --- a/app/translations/pl_PL.json +++ b/app/translations/pl_PL.json @@ -578,6 +578,7 @@ "serverUpload": "Wgraj ZIP Serwera", "serverVersion": "Wersja serwera", "sizeInGB": "Wielkość w GB", + "unsupported": "Wersje Minecrafta poniżej 1.8 nie są wspierane przez Crafty. Mimo to możesz je zainstalować - jednakże nie jesteśmy w stanie zagwarantować ich działanie.", "uploadButton": "Wgraj", "uploadZip": "Wgraj plik Zip dla imprtowania serwera", "zipPath": "Server Path" diff --git a/app/translations/th_TH.json b/app/translations/th_TH.json index a833cf1c..ce377492 100644 --- a/app/translations/th_TH.json +++ b/app/translations/th_TH.json @@ -578,6 +578,7 @@ "serverUpload": "อัปโหลดเซิร์ฟเวอร์ซิป", "serverVersion": "เวอร์ชันเซิร์ฟเวอร์", "sizeInGB": "ขนาดเป็นกิกะไบต์", + "unsupported": "Crafty ไม่รองรับ Minecraft เวอร์ชั่นต่ำกว่า 1.8 คุณยังสามารถติดตั้งได้ ผลลัพธ์จะแตกต่างกันออกไป", "uploadButton": "อัปโหลด", "uploadZip": "อัปโหลดไฟล์ซิปสำหรับการนำเข้าเซิร์ฟเวอร์", "zipPath": "เส้นทางเซิร์ฟเวอร์" diff --git a/app/translations/tr_TR.json b/app/translations/tr_TR.json index 9ab3a6c8..cf96f2b3 100644 --- a/app/translations/tr_TR.json +++ b/app/translations/tr_TR.json @@ -578,6 +578,7 @@ "serverUpload": "Sıkıştırılmış Sunucu Yükle", "serverVersion": "Sunucu Sürümü", "sizeInGB": "GB cinsinden boyut", + "unsupported": "Minecraft'ın 1.8'den eski sürümleri Crafty tarafından desteklenmemektedir. Yine de yükleyebilirsiniz. Sonuçlar değişkenlik gösterecektir.", "uploadButton": "Dosya Yükle", "uploadZip": "Sunucu İçe Aktarımı İçin Zip Dosyası Yükle", "zipPath": "Sunucu Konumu" diff --git a/app/translations/uk_UA.json b/app/translations/uk_UA.json index a7018a5f..a22c1de9 100644 --- a/app/translations/uk_UA.json +++ b/app/translations/uk_UA.json @@ -578,6 +578,7 @@ "serverUpload": "Вивантажити архівований сервер", "serverVersion": "Версія сервера", "sizeInGB": "Об'єм пам'яті в ГБ", + "unsupported": "Minecraft версії старіші ніж 1.8, не підтримуються Crafty. Ви все ще можете встановити їх, але результат буде непередбачуваний.", "uploadButton": "Вивантажити", "uploadZip": "Вивантажити архів(.zip) для імпорту сервера", "zipPath": "Шлях архіву сервера" diff --git a/app/translations/zh_CN.json b/app/translations/zh_CN.json index ffac7b3b..4ffa844b 100644 --- a/app/translations/zh_CN.json +++ b/app/translations/zh_CN.json @@ -579,6 +579,7 @@ "serverUpload": "上传打包为 Zip 文件的服务器", "serverVersion": "服务器版本", "sizeInGB": "大小(以 GB 为单位)", + "unsupported": "Crafty 不支持低于 1.8 的 Minecraft 版本。你仍可以安装,但结果无法保证。", "uploadButton": "上传", "uploadZip": "上传 Zip 文件以导入服务器", "zipPath": "服务器路径" From 68b0e611be8273844cba44c32348bc580e2159ba Mon Sep 17 00:00:00 2001 From: Andrew Date: Wed, 31 Jan 2024 22:00:45 -0500 Subject: [PATCH 62/84] Add new theme for lockout user --- app/frontend/static/assets/css/dark/style.css | 45 ++++++++++++++++++- app/frontend/templates/base.html | 2 +- .../templates/panel/panel_config.html | 2 +- 3 files changed, 46 insertions(+), 3 deletions(-) diff --git a/app/frontend/static/assets/css/dark/style.css b/app/frontend/static/assets/css/dark/style.css index 12320636..cae93650 100755 --- a/app/frontend/static/assets/css/dark/style.css +++ b/app/frontend/static/assets/css/dark/style.css @@ -55,6 +55,49 @@ root, --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; } +:root.anti-lockout { + /*CHANGE THESE FOR THEMES*/ + --tooltip-bg: rgb(215, 82, 0); + --select-bg: #b8772c; + --ram-bg: #4d4d4e; + --base-text: white; + --outline: #c73929; + --card-banner-bg: #de7c26; + --deep-bg: #912f2f; + --dropdown-bg: #c83b3b; + /*END THEME VARIATION*/ + --blue: #00aeef; + --indigo: #6610f2; + --purple: #ab8ce4; + --pink: #E91E63; + --red: #ff0017; + --orange: #fb9678; + --yellow: #ffd500; + --green: #3bd949; + --teal: #58d8a3; + --cyan: #57c7d4; + --white: #ffffff; + --white-smoke: #f3f5f6; + --gray: #6c757d; + --gray-light: #8ba2b5; + --gray-lightest: #f7f7f9; + --primary: #dbc900; + --secondary: #dde4eb; + --success: #adff84; + --info: #dbc900; + --warning: #ffaf00; + --danger: #ff6258; + --light: #fbfbfb; + --dark: #252C46; + --breakpoint-xs: 0; + --breakpoint-sm: 576px; + --breakpoint-md: 768px; + --breakpoint-lg: 992px; + --breakpoint-xl: 1200px; + --font-family-sans-serif: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; + --font-family-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; +} + :root.light { /*CHANGE THESE FOR THEMES*/ --tooltip-bg: white; @@ -322,7 +365,7 @@ sup { } a { - color: #007bff; + color: var(--primary); text-decoration: none; background-color: transparent; } diff --git a/app/frontend/templates/base.html b/app/frontend/templates/base.html index 546502a2..8d72ece6 100755 --- a/app/frontend/templates/base.html +++ b/app/frontend/templates/base.html @@ -587,7 +587,7 @@ link='/logout', link_msg="Click here to log out after you change your password. ⚠️", className='anti-lockout', - bg_color='#2090d6' + bg_color='#6887dc' ) } $('#support_logs').click(function () { diff --git a/app/frontend/templates/panel/panel_config.html b/app/frontend/templates/panel/panel_config.html index 5e9623b1..fee5c65d 100644 --- a/app/frontend/templates/panel/panel_config.html +++ b/app/frontend/templates/panel/panel_config.html @@ -281,7 +281,7 @@