mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'dev' into refactor/config-json
This commit is contained in:
commit
48b8b9d084
@ -92,15 +92,15 @@ docker-build-prod:
|
||||
- docker context create tls-environment
|
||||
- docker buildx create --name zedBuilder --use tls-environment
|
||||
- docker buildx build
|
||||
--cache-from type=registry,ref="$CI_REGISTRY_IMAGE"
|
||||
--cache-from type=registry,ref="$CI_REGISTRY_IMAGE:latest"
|
||||
--build-arg BUILDKIT_INLINE_CACHE=1
|
||||
--build-arg "BUILD_DATE=$(date +"%Y-%m-%dT%H:%M:%SZ")"
|
||||
--build-arg "BUILD_REF=${CI_COMMIT_SHA}"
|
||||
--build-arg "CRAFTY_VER=${VERSION}"
|
||||
--tag "$CI_REGISTRY_IMAGE"
|
||||
--platform linux/arm64/v8,linux/amd64 .
|
||||
- docker image tag "$CI_REGISTRY_IMAGE" "$CI_REGISTRY_IMAGE:${VERSION}"
|
||||
- docker image push -a
|
||||
--tag "$CI_REGISTRY_IMAGE:$VERSION"
|
||||
--tag "$CI_REGISTRY_IMAGE:latest"
|
||||
--platform linux/arm64/v8,linux/amd64
|
||||
--push .
|
||||
after_script:
|
||||
- |
|
||||
docker buildx rm zedBuilder && echo "Successfully Stopped builder instance" || echo "Failed to stop builder instance."
|
||||
|
20
CHANGELOG.md
20
CHANGELOG.md
@ -1,18 +1,32 @@
|
||||
# Changelog
|
||||
## --- [4.0.16] - 2022/10/09
|
||||
## --- [4.0.17] - 2022/TBD
|
||||
### New features
|
||||
TBD
|
||||
### Bug fixes
|
||||
TBD
|
||||
### Tweaks
|
||||
TBD
|
||||
### Lang
|
||||
TBD
|
||||
<br><br>
|
||||
|
||||
## --- [4.0.16] - 2022/10/23
|
||||
### New features
|
||||
- Automatically set update url for (new) server creation ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/487))
|
||||
- Add filter to logs panel ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/484))
|
||||
### Bug fixes
|
||||
- Fix conditional issue with zip imports/uploads ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/476))
|
||||
- Fix API Schedule updates ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/478))
|
||||
- Add port constraint for all server creation & api ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/479))
|
||||
- Clean up backup configs when deleting servers ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/480))
|
||||
- Add timeout to socket for servers with incorrect port selection ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/482))
|
||||
- Fix server_stats db file when deleting server ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/486))
|
||||
- Fix "cannot render after finish" from backup_now ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/489))
|
||||
- Fix Support Logs on windows by changing the way we declare projects working directory ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/491) | [Commit](https://gitlab.com/crafty-controller/crafty-4/-/commit/a6aa0f86797856a09c639317c5151c354f4024dc))
|
||||
### Tweaks
|
||||
- Fix sidebar to not move when scrolling ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/481))
|
||||
- Add the rest of CSS predefined colors to themes ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/477))
|
||||
### Lang
|
||||
TBD
|
||||
- Only send realtime stats when clients connected ([Merge Request](https://gitlab.com/crafty-controller/crafty-4/-/merge_requests/488))
|
||||
<br><br>
|
||||
|
||||
## --- [4.0.15] - 2022/10/02
|
||||
|
@ -1,12 +1,5 @@
|
||||
[![Crafty Logo](app/frontend/static/assets/images/logo_long.svg)](https://craftycontrol.com)
|
||||
|
||||
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
|
||||
[![Supported Python Versions](https://shields.io/badge/python-3.8%20%7C%203.9%20%7C%203.10%20-blue)](https://www.python.org)
|
||||
[![Version](https://img.shields.io/badge/release-v4.0.16-blue)](https://gitlab.com/crafty-controller/crafty-4/-/releases)
|
||||
[![Code Quality](https://img.shields.io/badge/code%20quality-10-brightgreen)](https://gitlab.com/crafty-controller/crafty-4)
|
||||
[![Build Status](https://gitlab.com/crafty-controller/crafty-4/badges/master/pipeline.svg)](https://gitlab.com/crafty-controller/crafty-4/-/commits/master)
|
||||
[![Licence](https://img.shields.io/gitlab/license/20430749)](https://gitlab.com/crafty-controller/crafty-4/-/blob/master/LICENSE)
|
||||
# Crafty Controller 4.0.16
|
||||
# Crafty Controller 4.0.17
|
||||
> Python based Control Panel for your Minecraft Server
|
||||
|
||||
## What is Crafty Controller?
|
||||
|
@ -120,6 +120,7 @@ class HelperServerStats:
|
||||
return None
|
||||
|
||||
def get_all_servers_stats(self):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
servers = HelperServers.get_all_defined_servers()
|
||||
server_data = []
|
||||
try:
|
||||
@ -136,18 +137,23 @@ class HelperServerStats:
|
||||
logger.error(
|
||||
f"Stats collection failed with error: {ex}. Was a server just created?"
|
||||
)
|
||||
self.database.close()
|
||||
return server_data
|
||||
|
||||
def get_history_stats(self, server_id, num_days):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
max_age = datetime.datetime.now() - timedelta(days=num_days)
|
||||
return (
|
||||
server_stats = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.created > max_age)
|
||||
.where(ServerStats.server_id == server_id)
|
||||
.execute(self.database)
|
||||
)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
return server_stats
|
||||
|
||||
def insert_server_stats(self, server_stats):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
server_id = server_stats.get("id", 0)
|
||||
|
||||
if server_id == 0:
|
||||
@ -176,13 +182,18 @@ class HelperServerStats:
|
||||
}
|
||||
).execute(self.database)
|
||||
|
||||
self.database.close()
|
||||
|
||||
def remove_old_stats(self, last_week):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
# self.select_database(self.server_id)
|
||||
ServerStats.delete().where(ServerStats.created < last_week).execute(
|
||||
self.database
|
||||
)
|
||||
self.database.close()
|
||||
|
||||
def get_latest_server_stats(self):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
latest = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
@ -190,12 +201,15 @@ class HelperServerStats:
|
||||
.limit(1)
|
||||
.get(self.database)
|
||||
)
|
||||
|
||||
self.database.close()
|
||||
try:
|
||||
return DatabaseShortcuts.get_data_obj(latest)
|
||||
except IndexError:
|
||||
return {}
|
||||
|
||||
def get_server_stats(self):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
stats = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
@ -203,63 +217,70 @@ class HelperServerStats:
|
||||
.limit(1)
|
||||
.first(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return DatabaseShortcuts.get_data_obj(stats)
|
||||
|
||||
def server_id_exists(self):
|
||||
# self.select_database(self.server_id)
|
||||
if not HelperServers.get_server_data_by_id(self.server_id):
|
||||
return False
|
||||
return True
|
||||
|
||||
def sever_crashed(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
ServerStats.update(crashed=True).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def set_import(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
ServerStats.update(importing=True).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def finish_import(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
ServerStats.update(importing=False).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def get_import_status(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
import_status = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
.get(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return import_status.importing
|
||||
|
||||
def server_crash_reset(self):
|
||||
if self.server_id is None:
|
||||
return
|
||||
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
ServerStats.update(crashed=False).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def is_crashed(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
svr: ServerStats = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
.get(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return svr.crashed
|
||||
|
||||
def set_update(self, value):
|
||||
if self.server_id is None:
|
||||
return
|
||||
# self.select_database(self.server_id)
|
||||
|
||||
self.database.connect(reuse_if_open=True)
|
||||
try:
|
||||
# Checks if server even exists
|
||||
ServerStats.select().where(ServerStats.server_id == self.server_id).execute(
|
||||
@ -267,22 +288,26 @@ class HelperServerStats:
|
||||
)
|
||||
except DoesNotExist as ex:
|
||||
logger.error(f"Database entry not found! {ex}")
|
||||
self.database.close()
|
||||
return
|
||||
|
||||
ServerStats.update(updating=value).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def get_update_status(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
update_status = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
.get(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return update_status.updating
|
||||
|
||||
def set_first_run(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
# Sets first run to false
|
||||
try:
|
||||
# Checks if server even exists
|
||||
@ -291,22 +316,25 @@ class HelperServerStats:
|
||||
)
|
||||
except Exception as ex:
|
||||
logger.error(f"Database entry not found! {ex}")
|
||||
self.database.close()
|
||||
return
|
||||
ServerStats.update(first_run=False).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def get_first_run(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
first_run = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
.get(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return first_run.first_run
|
||||
|
||||
def get_ttl_without_player(self):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
last_stat = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
@ -320,6 +348,7 @@ class HelperServerStats:
|
||||
.order_by(ServerStats.created.desc())
|
||||
.first(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return last_stat.created - last_stat_with_player.created
|
||||
|
||||
def can_stop_no_players(self, time_limit):
|
||||
@ -327,7 +356,7 @@ class HelperServerStats:
|
||||
return (time_limit == -1) or (ttl_no_players > time_limit)
|
||||
|
||||
def set_waiting_start(self, value):
|
||||
# self.select_database(self.server_id)
|
||||
self.database.connect(reuse_if_open=True)
|
||||
try:
|
||||
# Checks if server even exists
|
||||
ServerStats.select().where(ServerStats.server_id == self.server_id).execute(
|
||||
@ -335,15 +364,19 @@ class HelperServerStats:
|
||||
)
|
||||
except DoesNotExist as ex:
|
||||
logger.error(f"Database entry not found! {ex}")
|
||||
self.database.close()
|
||||
return
|
||||
ServerStats.update(waiting_start=value).where(
|
||||
ServerStats.server_id == self.server_id
|
||||
).execute(self.database)
|
||||
self.database.close()
|
||||
|
||||
def get_waiting_start(self):
|
||||
self.database.connect(reuse_if_open=True)
|
||||
waiting_start = (
|
||||
ServerStats.select()
|
||||
.where(ServerStats.server_id == self.server_id)
|
||||
.get(self.database)
|
||||
)
|
||||
self.database.close()
|
||||
return waiting_start.waiting_start
|
||||
|
@ -472,6 +472,15 @@ class Controller:
|
||||
data["create_type"] == "minecraft_java"
|
||||
and root_create_data["create_type"] == "download_jar"
|
||||
):
|
||||
# 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']}"
|
||||
)
|
||||
server_obj.executable_update_url = url
|
||||
self.servers.update_server(server_obj)
|
||||
self.server_jars.download_jar(
|
||||
create_data["category"],
|
||||
create_data["type"],
|
||||
@ -555,7 +564,12 @@ class Controller:
|
||||
user_id,
|
||||
server_type="minecraft-java",
|
||||
)
|
||||
|
||||
# modded update urls from server jars will only update the installer
|
||||
if jar != "modded":
|
||||
server_obj = self.servers.get_server_obj(new_id)
|
||||
url = f"https://serverjars.com/api/fetchJar/{jar}/{server}/{version}"
|
||||
server_obj.executable_update_url = url
|
||||
self.servers.update_server(server_obj)
|
||||
# download the jar
|
||||
self.server_jars.download_jar(
|
||||
jar, server, version, os.path.join(server_dir, server_file), new_id
|
||||
|
@ -1223,41 +1223,19 @@ class ServerInstance:
|
||||
# **********************************************************************************
|
||||
|
||||
def realtime_stats(self):
|
||||
total_players = 0
|
||||
max_players = 0
|
||||
servers_ping = []
|
||||
raw_ping_result = []
|
||||
raw_ping_result = self.get_raw_server_stats(self.server_id)
|
||||
|
||||
if f"{raw_ping_result.get('icon')}" == "b''":
|
||||
raw_ping_result["icon"] = False
|
||||
|
||||
servers_ping.append(
|
||||
{
|
||||
"id": raw_ping_result.get("id"),
|
||||
"started": raw_ping_result.get("started"),
|
||||
"running": raw_ping_result.get("running"),
|
||||
"cpu": raw_ping_result.get("cpu"),
|
||||
"mem": raw_ping_result.get("mem"),
|
||||
"mem_percent": raw_ping_result.get("mem_percent"),
|
||||
"world_name": raw_ping_result.get("world_name"),
|
||||
"world_size": raw_ping_result.get("world_size"),
|
||||
"server_port": raw_ping_result.get("server_port"),
|
||||
"int_ping_results": raw_ping_result.get("int_ping_results"),
|
||||
"online": raw_ping_result.get("online"),
|
||||
"max": raw_ping_result.get("max"),
|
||||
"players": raw_ping_result.get("players"),
|
||||
"desc": raw_ping_result.get("desc"),
|
||||
"version": raw_ping_result.get("version"),
|
||||
"icon": raw_ping_result.get("icon"),
|
||||
"crashed": self.is_crashed,
|
||||
}
|
||||
)
|
||||
# only get stats if clients are connected.
|
||||
# no point in burning cpu
|
||||
if len(self.helper.websocket_helper.clients) > 0:
|
||||
self.helper.websocket_helper.broadcast_page_params(
|
||||
"/panel/server_detail",
|
||||
{"id": str(self.server_id)},
|
||||
"update_server_details",
|
||||
total_players = 0
|
||||
max_players = 0
|
||||
servers_ping = []
|
||||
raw_ping_result = []
|
||||
raw_ping_result = self.get_raw_server_stats(self.server_id)
|
||||
|
||||
if f"{raw_ping_result.get('icon')}" == "b''":
|
||||
raw_ping_result["icon"] = False
|
||||
|
||||
servers_ping.append(
|
||||
{
|
||||
"id": raw_ping_result.get("id"),
|
||||
"started": raw_ping_result.get("started"),
|
||||
@ -1276,24 +1254,53 @@ class ServerInstance:
|
||||
"version": raw_ping_result.get("version"),
|
||||
"icon": raw_ping_result.get("icon"),
|
||||
"crashed": self.is_crashed,
|
||||
"created": datetime.datetime.now().strftime("%Y/%m/%d, %H:%M:%S"),
|
||||
},
|
||||
}
|
||||
)
|
||||
total_players += int(raw_ping_result.get("online"))
|
||||
max_players += int(raw_ping_result.get("max"))
|
||||
|
||||
self.record_server_stats()
|
||||
|
||||
if (len(servers_ping) > 0) & (len(self.helper.websocket_helper.clients) > 0):
|
||||
try:
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/panel/dashboard", "update_server_status", servers_ping
|
||||
if len(self.helper.websocket_helper.clients) > 0:
|
||||
self.helper.websocket_helper.broadcast_page_params(
|
||||
"/panel/server_detail",
|
||||
{"id": str(self.server_id)},
|
||||
"update_server_details",
|
||||
{
|
||||
"id": raw_ping_result.get("id"),
|
||||
"started": raw_ping_result.get("started"),
|
||||
"running": raw_ping_result.get("running"),
|
||||
"cpu": raw_ping_result.get("cpu"),
|
||||
"mem": raw_ping_result.get("mem"),
|
||||
"mem_percent": raw_ping_result.get("mem_percent"),
|
||||
"world_name": raw_ping_result.get("world_name"),
|
||||
"world_size": raw_ping_result.get("world_size"),
|
||||
"server_port": raw_ping_result.get("server_port"),
|
||||
"int_ping_results": raw_ping_result.get("int_ping_results"),
|
||||
"online": raw_ping_result.get("online"),
|
||||
"max": raw_ping_result.get("max"),
|
||||
"players": raw_ping_result.get("players"),
|
||||
"desc": raw_ping_result.get("desc"),
|
||||
"version": raw_ping_result.get("version"),
|
||||
"icon": raw_ping_result.get("icon"),
|
||||
"crashed": self.is_crashed,
|
||||
"created": datetime.datetime.now().strftime(
|
||||
"%Y/%m/%d, %H:%M:%S"
|
||||
),
|
||||
},
|
||||
)
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/status", "update_server_status", servers_ping
|
||||
)
|
||||
except:
|
||||
Console.critical("Can't broadcast server status to websocket")
|
||||
total_players += int(raw_ping_result.get("online"))
|
||||
max_players += int(raw_ping_result.get("max"))
|
||||
|
||||
self.record_server_stats()
|
||||
|
||||
if (len(servers_ping) > 0) & (
|
||||
len(self.helper.websocket_helper.clients) > 0
|
||||
):
|
||||
try:
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/panel/dashboard", "update_server_status", servers_ping
|
||||
)
|
||||
self.helper.websocket_helper.broadcast_page(
|
||||
"/status", "update_server_status", servers_ping
|
||||
)
|
||||
except:
|
||||
Console.critical("Can't broadcast server status to websocket")
|
||||
|
||||
def get_servers_stats(self):
|
||||
|
||||
|
@ -76,7 +76,7 @@ class AjaxHandler(BaseHandler):
|
||||
line = re.sub("(\033\\[(0;)?[0-9]*[A-z]?(;[0-9])?m?)", "", line)
|
||||
line = re.sub("[A-z]{2}\b\b", "", line)
|
||||
line = self.helper.log_colors(html.escape(line))
|
||||
self.write(f"{line}<br />")
|
||||
self.write(f"<span class='box'>{line}<br /></span>")
|
||||
# self.write(d.encode("utf-8"))
|
||||
|
||||
except Exception as e:
|
||||
|
@ -1,5 +1,5 @@
|
||||
{
|
||||
"major": 4,
|
||||
"minor": 0,
|
||||
"sub": 16
|
||||
"sub": 17
|
||||
}
|
||||
|
@ -294,9 +294,10 @@
|
||||
headers: { 'X-XSRFToken': token },
|
||||
url: '/ajax/backup_now?id=' + server_id,
|
||||
success: function (data) {
|
||||
location.reload();
|
||||
return;
|
||||
},
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
function del_backup(filename, id) {
|
||||
|
@ -42,10 +42,17 @@
|
||||
<div class="col-md-12">
|
||||
<div class="input-group">
|
||||
<div id="virt_console" class=""
|
||||
style="font-size: .8em; padding: 5px 10px; border: 1px solid var(--outline); background-color:var(--card-banner-bg);height:500px; overflow: scroll;">
|
||||
style="width: 100%; font-size: .8em; padding: 5px 10px; border: 1px solid var(--outline); background-color:var(--card-banner-bg);height:500px; overflow: scroll;">
|
||||
</div>
|
||||
</div>
|
||||
<br />
|
||||
<label for="ignore">{{ translate('serverDetails', 'filter', data['lang']) }}</label>
|
||||
<input type="text" class="form-control" name="ignore" id="searchbox" value="" required>
|
||||
<br />
|
||||
<br />
|
||||
<h4>{{ translate('serverDetails', 'filterList', data['lang']) }}</h4>
|
||||
<ul id="ignored-words" style="list-style: None;"></ul>
|
||||
<br />
|
||||
|
||||
|
||||
</div>
|
||||
@ -55,15 +62,131 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<span class="is-hidden">secret</span>
|
||||
</div>
|
||||
<style>
|
||||
.is-hidden {
|
||||
display: none;
|
||||
position: fixed !important;
|
||||
}
|
||||
</style>
|
||||
<!-- content-wrapper ends -->
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block js %}
|
||||
<script>
|
||||
// ##### Log Filter Block #####
|
||||
var lines = [];
|
||||
var words = [];
|
||||
if (localStorage.getItem("words")) {
|
||||
try {
|
||||
words = JSON.parse(localStorage.getItem("words"));
|
||||
} catch {
|
||||
words = [];
|
||||
}
|
||||
}
|
||||
|
||||
function hideFilteredWords() {
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
// Reinitialise line visibility
|
||||
lines[i].classList.remove("is-hidden");
|
||||
|
||||
// If we have no words to filter, continue.
|
||||
if (!words.length) continue;
|
||||
|
||||
// If we find our target word hide the line
|
||||
if (words.some(ai => lines[i].textContent.toLowerCase().includes(ai))) {
|
||||
lines[i].classList.add("is-hidden");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function sanitize(string) {
|
||||
return string.replace(/[`~!@#$%^&*()_|+\-=?;:'",.<>\{\}\[\]\\\/]/gi, '');
|
||||
}
|
||||
|
||||
function deleteWord(item) {
|
||||
let safe_item = sanitize(item);
|
||||
words.splice(words.indexOf(item), 1);
|
||||
if (safe_item) $("#" + safe_item.replaceAll(" ", "-")).remove();
|
||||
|
||||
hideFilteredWords();
|
||||
localStorage.setItem("words", JSON.stringify(words));
|
||||
}
|
||||
|
||||
//A little delay
|
||||
let typingTimer;
|
||||
let typeInterval = 500;
|
||||
let searchInput = document.getElementById('searchbox');
|
||||
searchInput.addEventListener('keyup', (e) => {
|
||||
clearTimeout(typingTimer);
|
||||
typingTimer = setTimeout(hideFilteredWords, typeInterval);
|
||||
|
||||
// Return/Enter key press otherwise bail
|
||||
if (e.keyCode !== 13) return;
|
||||
|
||||
let word = document.getElementById("searchbox").value;
|
||||
document.getElementById("searchbox").value = "";
|
||||
word = word.toLowerCase();
|
||||
word = word.replace(/[`'"]/gi, " ");
|
||||
|
||||
let safe_word = sanitize(word).trimLeft();
|
||||
|
||||
if (word.includes("\\n")) {
|
||||
window.alert("Nice try...");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!safe_word) {
|
||||
window.alert("Illegal character detected");
|
||||
return;
|
||||
}
|
||||
|
||||
if (words.includes(safe_word)) return;
|
||||
|
||||
// Display filtered word
|
||||
words.push(word);
|
||||
$("#ignored-words").append(
|
||||
`<li id=${safe_word.replaceAll(" ", "-")}>` +
|
||||
"<div class='card-header header-sm d-flex justify-content-between align-items-center'>" +
|
||||
`${word} <button class='btn btn-danger' onclick='deleteWord("${word}")' >` +
|
||||
"<i class='fas fa-trash'></i></button></div></li>"
|
||||
);
|
||||
|
||||
// Set word filters in browser cache
|
||||
localStorage.setItem("words", JSON.stringify(words));
|
||||
});
|
||||
|
||||
function populateWords() {
|
||||
words.map(word => {
|
||||
let safe_word = sanitize(word);
|
||||
|
||||
$("#ignored-words").append(
|
||||
`<li id=${safe_word.replaceAll(" ", "-")}>` +
|
||||
"<div class='card-header header-sm d-flex justify-content-between align-items-center'>" +
|
||||
`${word} <button class='btn btn-danger' onclick='deleteWord("${word}")' >` +
|
||||
"<i class='fas fa-trash'></i></button></div></li>"
|
||||
);
|
||||
});
|
||||
}
|
||||
// ##### End Log Filter Block #####
|
||||
|
||||
// Used to get cookies from browser - this is part of tornados xsrf protection
|
||||
// (it's for extra security)
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
// Reset Scroll
|
||||
function scroll() {
|
||||
var logview = $('#virt_console');
|
||||
if (logview.length)
|
||||
logview.scrollTop(logview[0].scrollHeight - logview.height());
|
||||
}
|
||||
|
||||
// Populate logs and filter if present
|
||||
const serverId = new URLSearchParams(document.location.search).get('id')
|
||||
function get_server_log() {
|
||||
if (!$("#stop_scroll").is(':checked')) {
|
||||
@ -75,32 +198,17 @@
|
||||
console.log('Got Log From Server')
|
||||
$('#virt_console').html(data);
|
||||
scroll();
|
||||
lines = document.querySelectorAll('.box');
|
||||
hideFilteredWords();
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
//used to get cookies from browser - this is part of tornados xsrf protection - it's for extra security
|
||||
function getCookie(name) {
|
||||
var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");
|
||||
return r ? r[1] : undefined;
|
||||
}
|
||||
|
||||
$(document).ready(function () {
|
||||
console.log("ready!");
|
||||
get_server_log()
|
||||
|
||||
|
||||
get_server_log();
|
||||
populateWords();
|
||||
});
|
||||
|
||||
|
||||
function scroll() {
|
||||
var logview = $('#virt_console');
|
||||
if (logview.length)
|
||||
logview.scrollTop(logview[0].scrollHeight - logview.height());
|
||||
}
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
{% end %}
|
||||
{% end %}
|
||||
|
@ -360,7 +360,9 @@
|
||||
"serverDetails": "Server Details",
|
||||
"terminal": "Terminal",
|
||||
"metrics": "Metrics",
|
||||
"reset": "Reset Scroll"
|
||||
"reset": "Reset Scroll",
|
||||
"filter": "Filter Logs",
|
||||
"filterList": "Filtered Words"
|
||||
},
|
||||
"serverFiles": {
|
||||
"clickUpload": "Click here to select your files",
|
||||
|
18
main.py
18
main.py
@ -198,8 +198,22 @@ if __name__ == "__main__":
|
||||
if not controller.check_system_user():
|
||||
controller.add_system_user()
|
||||
|
||||
project_root = os.path.dirname(__file__)
|
||||
controller.set_project_root(project_root)
|
||||
if getattr(sys, "frozen", False):
|
||||
application_path = os.path.dirname(sys.executable)
|
||||
running_mode = "Frozen/executable"
|
||||
else:
|
||||
try:
|
||||
app_full_path = os.path.realpath(__file__)
|
||||
application_path = os.path.dirname(app_full_path)
|
||||
running_mode = "Non-interactive (e.g. 'python main.py')"
|
||||
except NameError:
|
||||
application_path = os.getcwd()
|
||||
running_mode = "Interactive"
|
||||
|
||||
controller.set_project_root(application_path)
|
||||
Console.debug(f"Execution Mode: {running_mode}")
|
||||
Console.debug(f"Application path : '{application_path}'")
|
||||
|
||||
controller.clear_unexecuted_commands()
|
||||
controller.clear_support_status()
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user