Using API Call for Status Page

This commit is contained in:
Silversthorn 2023-09-02 21:51:28 +02:00
parent 2cd0b527d9
commit 34fe9c1326
10 changed files with 137 additions and 268 deletions

View File

@ -50,6 +50,7 @@ class ServerStats(Model):
max = IntegerField(default=0) max = IntegerField(default=0)
players = CharField(default="") players = CharField(default="")
desc = CharField(default="Unable to Connect") desc = CharField(default="Unable to Connect")
icon = CharField(default="")
version = CharField(default="") version = CharField(default="")
updating = BooleanField(default=False) updating = BooleanField(default=False)
waiting_start = BooleanField(default=False) waiting_start = BooleanField(default=False)
@ -183,6 +184,7 @@ class HelperServerStats:
ServerStats.max: server_stats.get("max", False), ServerStats.max: server_stats.get("max", False),
ServerStats.players: server_stats.get("players", False), ServerStats.players: server_stats.get("players", False),
ServerStats.desc: server_stats.get("desc", False), ServerStats.desc: server_stats.get("desc", False),
ServerStats.icon: server_stats.get("icon", None),
ServerStats.version: server_stats.get("version", False), ServerStats.version: server_stats.get("version", False),
} }
).execute(self.database) ).execute(self.database)

View File

@ -1536,14 +1536,6 @@ class ServerInstance:
except: except:
Console.critical("Can't broadcast server status to websocket") Console.critical("Can't broadcast server status to websocket")
if (len(servers_ping) > 0) & (len(WebSocketManager().public_clients) > 0):
try:
WebSocketManager().broadcast_page(
"/status", "update_server_status", servers_ping
)
except:
Console.critical("Can't broadcast server status to websocket")
def get_servers_stats(self): def get_servers_stats(self):
server_stats = {} server_stats = {}
@ -1605,6 +1597,7 @@ class ServerInstance:
"players": ping_data.get("players", False), "players": ping_data.get("players", False),
"desc": ping_data.get("server_description", False), "desc": ping_data.get("server_description", False),
"version": ping_data.get("server_version", False), "version": ping_data.get("server_version", False),
"icon": ping_data.get("server_icon"),
} }
else: else:
server_stats = { server_stats = {
@ -1623,6 +1616,7 @@ class ServerInstance:
"players": False, "players": False,
"desc": False, "desc": False,
"version": False, "version": False,
"icon": None,
} }
return server_stats return server_stats
@ -1671,7 +1665,6 @@ class ServerInstance:
} }
server_stats = {} server_stats = {}
server = HelperServers.get_server_obj(server_id)
if not server: if not server:
return {} return {}
server_dt = HelperServers.get_server_data_by_id(server_id) server_dt = HelperServers.get_server_data_by_id(server_id)

View File

@ -12,6 +12,7 @@ from app.classes.web.routes.api.roles.index import ApiRolesIndexHandler
from app.classes.web.routes.api.roles.role.index import ApiRolesRoleIndexHandler from app.classes.web.routes.api.roles.role.index import ApiRolesRoleIndexHandler
from app.classes.web.routes.api.roles.role.servers import ApiRolesRoleServersHandler from app.classes.web.routes.api.roles.role.servers import ApiRolesRoleServersHandler
from app.classes.web.routes.api.roles.role.users import ApiRolesRoleUsersHandler from app.classes.web.routes.api.roles.role.users import ApiRolesRoleUsersHandler
from app.classes.web.routes.api.servers.index import ApiServersIndexHandler from app.classes.web.routes.api.servers.index import ApiServersIndexHandler
from app.classes.web.routes.api.servers.server.action import ( from app.classes.web.routes.api.servers.server.action import (
ApiServersServerActionHandler, ApiServersServerActionHandler,
@ -21,6 +22,9 @@ from app.classes.web.routes.api.servers.server.logs import ApiServersServerLogsH
from app.classes.web.routes.api.servers.server.public import ( from app.classes.web.routes.api.servers.server.public import (
ApiServersServerPublicHandler, ApiServersServerPublicHandler,
) )
from app.classes.web.routes.api.servers.server.status import (
ApiServersServerStatusHandler,
)
from app.classes.web.routes.api.servers.server.stats import ApiServersServerStatsHandler from app.classes.web.routes.api.servers.server.stats import ApiServersServerStatsHandler
from app.classes.web.routes.api.servers.server.history import ( from app.classes.web.routes.api.servers.server.history import (
ApiServersServerHistoryHandler, ApiServersServerHistoryHandler,
@ -110,6 +114,11 @@ def api_handlers(handler_args):
ApiServersIndexHandler, ApiServersIndexHandler,
handler_args, handler_args,
), ),
(
r"/api/v2/servers/status/?",
ApiServersServerStatusHandler,
handler_args,
),
( (
r"/api/v2/servers/([0-9]+)/?", r"/api/v2/servers/([0-9]+)/?",
ApiServersServerIndexHandler, ApiServersServerIndexHandler,

View File

@ -0,0 +1,32 @@
import logging
from app.classes.web.base_api_handler import BaseApiHandler
logger = logging.getLogger(__name__)
class ApiServersServerStatusHandler(BaseApiHandler):
def get(self):
servers_status = []
servers_list = self.controller.servers.get_all_servers_stats()
for server in servers_list:
if server.get("server_data").get("show_status") is True:
servers_status.append(
{
"id": server.get("server_data").get("server_id"),
"world_name": server.get("stats").get("world_name"),
"running": server.get("stats").get("running"),
"online": server.get("stats").get("online"),
"max": server.get("stats").get("max"),
"version": server.get("stats").get("version"),
"desc": server.get("stats").get("desc"),
"icon": server.get("stats").get("icon"),
}
)
self.finish_json(
200,
{
"status": "ok",
"data": servers_status,
},
)

View File

@ -34,7 +34,7 @@ from app.classes.web.api_handler import (
ListServers, ListServers,
SendCommand, SendCommand,
) )
from app.classes.web.websocket_handler import AuthSocketHandler, PublicSocketHandler from app.classes.web.websocket_handler import AuthSocketHandler
from app.classes.web.static_handler import CustomStaticHandler from app.classes.web.static_handler import CustomStaticHandler
from app.classes.web.upload_handler import UploadHandler from app.classes.web.upload_handler import UploadHandler
from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
@ -154,7 +154,6 @@ class Webserver:
(r"/ajax/(.*)", AjaxHandler, handler_args), (r"/ajax/(.*)", AjaxHandler, handler_args),
(r"/files/(.*)", FileHandler, handler_args), (r"/files/(.*)", FileHandler, handler_args),
(r"/ws/auth", AuthSocketHandler, handler_args), (r"/ws/auth", AuthSocketHandler, handler_args),
(r"/ws/public", PublicSocketHandler, handler_args),
(r"/upload", UploadHandler, handler_args), (r"/upload", UploadHandler, handler_args),
(r"/status", StatusHandler, handler_args), (r"/status", StatusHandler, handler_args),
# API Routes V1 # API Routes V1

View File

@ -176,45 +176,3 @@ class AuthSocketHandler(BaseSocketHandler):
) )
WebSocketManager().add_client(self) WebSocketManager().add_client(self)
logger.debug("Opened WebSocket connection") logger.debug("Opened WebSocket connection")
class PublicSocketHandler(BaseSocketHandler):
ws_state = EnumWebSocketState.WS_PUBLIC
ws_authorized_pages = {"404", "error", "login", "offline", "status"}
ws_authorized_events = {"update_server_status"} # Must be overridden at init
page = None
page_query_params = None
controller = None
tasks_manager = None
translator = None
io_loop = None
def initialize(
self, helper=None, controller=None, tasks_manager=None, translator=None
):
self.helper = helper
self.controller = controller
self.tasks_manager = tasks_manager
self.translator = translator
self.io_loop = tornado.ioloop.IOLoop.current()
def get_user_id(self):
return None
def check_auth(self):
return False
# pylint: disable=arguments-differ
def open(self):
logger.debug("Checking Public WebSocket")
self.handle()
def handle(self):
self.page = self.get_query_argument("page")
self.page_query_params = dict(
parse_qsl(
Helpers.remove_prefix(self.get_query_argument("page_query_params"), "?")
)
)
WebSocketManager().add_client(self)
logger.debug("Opened Public WebSocket connection")

View File

@ -58,13 +58,11 @@
</div> </div>
<div class="wrapper my-auto ml-auto ml-lg-4"> <div class="wrapper my-auto ml-auto ml-lg-4">
<p id="cpu_data" class="mb-0 text-success" data-toggle="tooltip" data-placement="top" data-html="true" <p id="cpu_data" class="mb-0 text-success" data-toggle="tooltip" data-placement="top" data-html="true" title="{% raw translate('dashboard', 'cpuCores', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cores') }} <br /> {% raw translate('dashboard', 'cpuCurFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cur_freq') }} <br /> {% raw translate('dashboard', 'cpuMaxFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_max_freq') }}">
title="{% raw translate('dashboard', 'cpuCores', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cores') }} <br /> {% raw translate('dashboard', 'cpuCurFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_cur_freq') }} <br /> {% raw translate('dashboard', 'cpuMaxFreq', data['lang']) %}: {{ data.get('hosts_data').get('cpu_max_freq') }}">
{{ translate('dashboard', 'cpuUsage', data['lang']) }}: <span id="cpu_usage">{{ {{ translate('dashboard', 'cpuUsage', data['lang']) }}: <span id="cpu_usage">{{
data.get('hosts_data').get('cpu_usage') }}</span> data.get('hosts_data').get('cpu_usage') }}</span>
</p> </p>
<p id="mem_usage" class="mb-0 text-danger" data-toggle="tooltip" data-placement="top" <p id="mem_usage" class="mb-0 text-danger" data-toggle="tooltip" data-placement="top" title="{{ translate('dashboard', 'memUsage', data['lang']) }}: {{ data.get('hosts_data').get('mem_usage') }}">
title="{{ translate('dashboard', 'memUsage', data['lang']) }}: {{ data.get('hosts_data').get('mem_usage') }}">
{{ translate('dashboard', 'memUsage', data['lang']) }}: <span id="mem_percent">{{ {{ translate('dashboard', 'memUsage', data['lang']) }}: <span id="mem_percent">{{
data.get('hosts_data').get('mem_percent') }}%</span> data.get('hosts_data').get('mem_percent') }}%</span>
</p> </p>
@ -111,12 +109,9 @@
{% for item in data['hosts_data']['disk_json'] %} {% for item in data['hosts_data']['disk_json'] %}
{% if item["mount"] in data["monitored"] %} {% if item["mount"] in data["monitored"] %}
<div id="{{item['device']}}" class="col-xl-3 col-lg-3 col-md-4 col-12"> <div id="{{item['device']}}" class="col-xl-3 col-lg-3 col-md-4 col-12">
<h4 class="mb-0 font-weight-semibold d-inline-block text-truncate storage-heading" <h4 class="mb-0 font-weight-semibold d-inline-block text-truncate storage-heading" id="title_{{item['device']}}" data-toggle="tooltip" data-placement="bottom" title="{{item['mount']}}" style="max-width: 100%;"><i class="fas fa-hdd"></i>
id="title_{{item['device']}}" data-toggle="tooltip" data-placement="bottom"
title="{{item['mount']}}" style="max-width: 100%;"><i class="fas fa-hdd"></i>
{{item["mount"]}}</h4> {{item["mount"]}}</h4>
<div class="progress d-inline-block" <div class="progress d-inline-block" style="height: 20px; width: 100%; background-color: rgb(139, 139, 139) !important;">
style="height: 20px; width: 100%; background-color: rgb(139, 139, 139) !important;">
<div class="progress-bar <div class="progress-bar
{% if item['percent_used'] <= 58 %} {% if item['percent_used'] <= 58 %}
bg-success bg-success
@ -125,8 +120,7 @@
{% else %} {% else %}
bg-danger bg-danger
{% end %} {% end %}
" role="progressbar" style="color: black; height: 100%; width: {{item['percent_used']}}%;" " role="progressbar" style="color: black; height: 100%; width: {{item['percent_used']}}%;" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">{{item["used"]}} /
aria-valuenow="0" aria-valuemin="0" aria-valuemax="100">{{item["used"]}} /
{{item["total"]}} {{item["total"]}}
</div> </div>
</div> </div>
@ -153,9 +147,7 @@
data['lang']) }}</h4> data['lang']) }}</h4>
{% if len(data['servers']) > 0 %} {% if len(data['servers']) > 0 %}
{% if data['user_data']['hints'] %} {% if data['user_data']['hints'] %}
<span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" , <span class="too_small" title="{{ translate('dashboard', 'cannotSeeOnMobile', data['lang']) }}" , data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" , data-placement="top"></span>
data-content="{{ translate('dashboard', 'cannotSeeOnMobile2', data['lang']) }}" ,
data-placement="top"></span>
{% end %} {% end %}
{% end %} {% end %}
<div><a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{ <div><a class="nav-link" href="/server/step1"><i class="fas fa-plus-circle"></i> &nbsp; {{
@ -193,8 +185,7 @@
<td draggable="false"> <td draggable="false">
<i class="fas fa-server"></i> <i class="fas fa-server"></i>
{% if server['alert'] %} {% if server['alert'] %}
<a style="color: red !important;" draggable="false" <a style="color: red !important;" draggable="false" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
href="/panel/server_detail?id={{server['server_data']['server_id']}}">
{{ server['server_data']['server_name'] }}&nbsp; <i class="fas fa-exclamation-triangle"></i> {{ server['server_data']['server_name'] }}&nbsp; <i class="fas fa-exclamation-triangle"></i>
</a> </a>
{% else %} {% else %}
@ -208,13 +199,11 @@
{% if server['user_command_permission'] %} {% if server['user_command_permission'] %}
{% if server['stats']['importing'] and server['stats']['running'] %} {% if server['stats']['importing'] and server['stats']['running'] %}
<!-- WHAT HAPPENED HERE --> <!-- WHAT HAPPENED HERE -->
<a data-id="{{server['server_data']['server_id']}}" class=""><i <a data-id="{{server['server_data']['server_id']}}" class=""><i class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'installing',
class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'installing',
data['lang']) }}</i></a> data['lang']) }}</i></a>
{% elif server['stats']['updating']%} {% elif server['stats']['updating']%}
<!-- WHAT HAPPENED HERE --> <!-- WHAT HAPPENED HERE -->
<a data-id="{{server['server_data']['server_id']}}" class=""><i <a data-id="{{server['server_data']['server_id']}}" class=""><i class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'updating',
class="fa fa-spinner fa-spin"></i>&nbsp;{{ translate('serverTerm', 'updating',
data['lang']) }}</i></a> data['lang']) }}</i></a>
{% elif server['stats']['waiting_start']%} {% elif server['stats']['waiting_start']%}
<!-- WHAT HAPPENED HERE --> <!-- WHAT HAPPENED HERE -->
@ -226,31 +215,25 @@
{{ translate('serverTerm', 'importing', {{ translate('serverTerm', 'importing',
data['lang']) }}</a> data['lang']) }}</a>
{% elif server['stats']['running'] %} {% elif server['stats']['running'] %}
<a data-id="{{server['server_data']['server_id']}}" class="stop_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="stop_button" data-toggle="tooltip" title="{{ translate('dashboard', 'stop' , data['lang']) }}">
title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<i class="fas fa-stop"></i> <i class="fas fa-stop"></i>
</a> &nbsp; </a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="restart_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="restart_button" data-toggle="tooltip" title="{{ translate('dashboard', 'restart' , data['lang']) }}">
title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<i class="fas fa-sync"></i> <i class="fas fa-sync"></i>
</a> &nbsp; </a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i> <i class="fas fa-skull"></i>
</a> &nbsp; </a> &nbsp;
{% else %} {% else %}
<a data-id="{{server['server_data']['server_id']}}" class="play_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="play_button" data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
title="{{ translate('dashboard', 'start' , data['lang']) }}">
<i class="fas fa-play"></i> <i class="fas fa-play"></i>
</a> &nbsp; </a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="clone_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="clone_button" data-toggle="tooltip" title="{{ translate('dashboard', 'clone' , data['lang']) }}">
title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<i class="fas fa-clone"></i> <i class="fas fa-clone"></i>
</a> &nbsp; </a> &nbsp;
<a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" <a data-id="{{server['server_data']['server_id']}}" class="kill_button" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i> <i class="fas fa-skull"></i>
</a> &nbsp; </a> &nbsp;
{% end %} {% end %}
@ -258,8 +241,7 @@
</td> </td>
<td draggable="false" id="server_cpu_{{server['server_data']['server_id']}}"> <td draggable="false" id="server_cpu_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" <div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['cpu']}}">
title="{{server['stats']['cpu']}}">
<div class="progress-bar <div class="progress-bar
{% if server['stats']['cpu'] <= 33 %} {% if server['stats']['cpu'] <= 33 %}
bg-success bg-success
@ -268,15 +250,13 @@
{% else %} {% else %}
bg-danger bg-danger
{% end %} {% end %}
" role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" " role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
aria-valuemin="0" aria-valuemax="100"></div>
</div> </div>
{{server['stats']['cpu']}}% {{server['stats']['cpu']}}%
</td> </td>
<td draggable="false" id="server_mem_{{server['server_data']['server_id']}}"> <td draggable="false" id="server_mem_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" <div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['mem']}}">
title="{{server['stats']['mem']}}">
<div class="progress-bar <div class="progress-bar
{% if server['stats']['mem_percent'] <= 33 %} {% if server['stats']['mem_percent'] <= 33 %}
bg-success bg-success
@ -285,8 +265,7 @@
{% else %} {% else %}
bg-danger bg-danger
{% end %} {% end %}
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" " role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
aria-valuemin="0" aria-valuemax="100"></div>
</div> </div>
{{server['stats']['mem_percent']}}% - {{server['stats']['mem_percent']}}% -
@ -305,8 +284,7 @@
data['lang']) }} <br /> data['lang']) }} <br />
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
<div id="desc_id" <div id="desc_id" style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">{{
style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">{{
server['stats']['desc'] }}</div> <br /> server['stats']['desc'] }}</div> <br />
{% end %} {% end %}
@ -334,16 +312,14 @@
<br /> <br />
<br /> <br />
</td> </td>
<span class="server-player-totals" id="server_players_{{server['server_data']['server_id']}}" <span class="server-player-totals" id="server_players_{{server['server_data']['server_id']}}" data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}"></span>
data-players="{{ server['stats']['online']}}" data-max="{{ server['stats']['max'] }}"></span>
</tr> </tr>
{% end %} {% end %}
</div> </div>
</span> </span>
{% for server in data['failed_servers'] %} {% for server in data['failed_servers'] %}
<tr id="{{server['server_id']}}" draggable="false"> <tr id="{{server['server_id']}}" draggable="false">
<td class="text-warning"><i class="fas fa-server"></i>&nbsp;<a class="text-warning" <td class="text-warning"><i class="fas fa-server"></i>&nbsp;<a class="text-warning" href="/panel/server_detail?id={{server['server_id']}}&subpage=config">{{server['server_name']}}</a>
href="/panel/server_detail?id={{server['server_id']}}&subpage=config">{{server['server_name']}}</a>
</td> </td>
<td></td> <td></td>
<td></td> <td></td>
@ -368,28 +344,22 @@
<div class="row"> <div class="row">
<div class="col-10 col-lg-3 mx-0 px-0"> <div class="col-10 col-lg-3 mx-0 px-0">
{% if server['alert'] %} {% if server['alert'] %}
<a style="color: red !important" class="btn btn-link d-flex justify-content-start" type="button" <a style="color: red !important" class="btn btn-link d-flex justify-content-start" type="button" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
href="/panel/server_detail?id={{server['server_data']['server_id']}}"> <i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}&nbsp; <i class="fas fa-exclamation-triangle"></i>
<i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}&nbsp; <i
class="fas fa-exclamation-triangle"></i>
</a> </a>
{% else %} {% else %}
<a class="btn btn-link d-flex justify-content-start" type="button" <a class="btn btn-link d-flex justify-content-start" type="button" href="/panel/server_detail?id={{server['server_data']['server_id']}}">
href="/panel/server_detail?id={{server['server_data']['server_id']}}">
<i class="fas fa-server"></i> {{ server['server_data']['server_name'] }} <i class="fas fa-server"></i> {{ server['server_data']['server_name'] }}
</a> </a>
{% end %} {% end %}
</div> </div>
<div class="col-2 col-lg-3 mx-0 px-0"> <div class="col-2 col-lg-3 mx-0 px-0">
<a class="btn btn-link d-flex justify-content-center" type="button" data-toggle="collapse" <a class="btn btn-link d-flex justify-content-center" type="button" data-toggle="collapse" data-target="#collapse-{{server['server_data']['server_id']}}" aria-expanded="false" aria-controls="collapse-{{server['server_data']['server_id']}}">
data-target="#collapse-{{server['server_data']['server_id']}}" aria-expanded="false"
aria-controls="collapse-{{server['server_data']['server_id']}}">
<i class="fas fa-chart-bar"></i> <i class="fas fa-chart-bar"></i>
</a> </a>
</div> </div>
<div class="col-4 col-lg-3 mx-0 px-0"> <div class="col-4 col-lg-3 mx-0 px-0">
<a id="m_server_running_status_{{server['server_data']['server_id']}}" <a id="m_server_running_status_{{server['server_data']['server_id']}}" class="btn btn-link d-flex justify-content-start" type="button">
class="btn btn-link d-flex justify-content-start" type="button">
{% if server['stats']['running'] %} {% if server['stats']['running'] %}
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online', <span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online',
data['lang']) }}</span> data['lang']) }}</span>
@ -410,23 +380,17 @@
{% if server['stats']['running'] %} {% if server['stats']['running'] %}
<div class="row"> <div class="row">
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn btn-link stop_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'stop' , data['lang']) }}">
class="btn btn-link stop_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'stop' , data['lang']) }}">
<i class="fas fa-stop"></i> <i class="fas fa-stop"></i>
</a> </a>
</div> </div>
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn btn-link restart_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'restart' , data['lang']) }}">
class="btn btn-link restart_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'restart' , data['lang']) }}">
<i class="fas fa-sync"></i> <i class="fas fa-sync"></i>
</a> </a>
</div> </div>
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn btn-link kill_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
class="btn btn-link kill_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i> <i class="fas fa-skull"></i>
</a> </a>
</div> </div>
@ -452,31 +416,24 @@
{% elif server['stats']['importing']%} {% elif server['stats']['importing']%}
<div class="row"> <div class="row">
<div class="col-12 px-0"> <div class="col-12 px-0">
<a data-id="{{server['server_data']['server_id']}}" class="btn btn-link"><i <a data-id="{{server['server_data']['server_id']}}" class="btn btn-link"><i class="fa fa-spinner fa-spin"></i>
class="fa fa-spinner fa-spin"></i>
{{ translate('serverTerm', 'importing', data['lang']) }}</a> {{ translate('serverTerm', 'importing', data['lang']) }}</a>
</div> </div>
</div> </div>
{% else %} {% else %}
<div class="row"> <div class="row">
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn play_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'start' , data['lang']) }}">
class="btn play_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'start' , data['lang']) }}">
<i class="fas fa-play"></i> <i class="fas fa-play"></i>
</a> </a>
</div> </div>
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn clone_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'clone' , data['lang']) }}">
class="btn clone_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'clone' , data['lang']) }}">
<i class="fas fa-clone"></i> <i class="fas fa-clone"></i>
</a> </a>
</div> </div>
<div class="col-4 px-0"> <div class="col-4 px-0">
<a data-id="{{server['server_data']['server_id']}}" <a data-id="{{server['server_data']['server_id']}}" class="btn kill_button actions_serveritem" data-toggle="tooltip" title="{{ translate('dashboard', 'kill' , data['lang']) }}">
class="btn kill_button actions_serveritem" data-toggle="tooltip"
title="{{ translate('dashboard', 'kill' , data['lang']) }}">
<i class="fas fa-skull"></i></a> <i class="fas fa-skull"></i></a>
</div> </div>
</div> </div>
@ -488,15 +445,13 @@
</h2> </h2>
</div> </div>
<div id="collapse-{{server['server_data']['server_id']}}" class="collapse" <div id="collapse-{{server['server_data']['server_id']}}" class="collapse" aria-labelledby="heading-{{server['server_data']['server_id']}}" data-parent="#accordionServers">
aria-labelledby="heading-{{server['server_data']['server_id']}}" data-parent="#accordionServers">
<div class="card-body"> <div class="card-body">
<div class="row"> <div class="row">
<div class="col-6"> <div class="col-6">
<h6>{{ translate('dashboard', 'cpuUsage', data['lang']) }}</h6> <h6>{{ translate('dashboard', 'cpuUsage', data['lang']) }}</h6>
<div id="m_server_cpu_{{server['server_data']['server_id']}}"> <div id="m_server_cpu_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" <div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['cpu']}}">
title="{{server['stats']['cpu']}}">
<div class="progress-bar <div class="progress-bar
{% if server['stats']['cpu'] <= 33 %} {% if server['stats']['cpu'] <= 33 %}
bg-success bg-success
@ -505,8 +460,7 @@
{% else %} {% else %}
bg-danger bg-danger
{% end %} {% end %}
" role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" aria-valuemin="0" " role="progressbar" style="width: {{server['stats']['cpu']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
aria-valuemax="100"></div>
</div> </div>
{{server['stats']['cpu']}}% {{server['stats']['cpu']}}%
</div> </div>
@ -514,8 +468,7 @@
<div class="col-6"> <div class="col-6">
<h6>{{ translate('dashboard', 'memUsage', data['lang']) }}</h6> <h6>{{ translate('dashboard', 'memUsage', data['lang']) }}</h6>
<div draggable="false" id="m_server_mem_{{server['server_data']['server_id']}}"> <div draggable="false" id="m_server_mem_{{server['server_data']['server_id']}}">
<div class="progress mb-1" data-toggle="tooltip" data-placement="top" <div class="progress mb-1" data-toggle="tooltip" data-placement="top" title="{{server['stats']['mem']}}">
title="{{server['stats']['mem']}}">
<div class="progress-bar <div class="progress-bar
{% if server['stats']['mem_percent'] <= 33 %} {% if server['stats']['mem_percent'] <= 33 %}
bg-success bg-success
@ -524,8 +477,7 @@
{% else %} {% else %}
bg-danger bg-danger
{% end %} {% end %}
" role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" " role="progressbar" style="width: {{server['stats']['mem_percent']}}%" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100"></div>
aria-valuemin="0" aria-valuemax="100"></div>
</div> </div>
{{server['stats']['mem_percent']}}% - {{server['stats']['mem_percent']}}% -
@ -554,8 +506,7 @@
data['lang']) }} <br /> data['lang']) }} <br />
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
<div id="desc_id" <div id="desc_id" style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">
style="overflow-wrap: break-word !important; max-width: 85px !important; overflow: scroll;">
{{ server['stats']['desc'] }}</div> <br /> {{ server['stats']['desc'] }}</div> <br />
{% end %} {% end %}
@ -796,6 +747,7 @@
/* Update Motd */ /* Update Motd */
let motd = ""; let motd = "";
if (server.desc) { if (server.desc) {
m_motd = `<span id="m_input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span>`;
motd = `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span>`; motd = `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span>`;
m_server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; overflow: auto;">' + motd + '</div>' + "<br />"; m_server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; overflow: auto;">' + motd + '</div>' + "<br />";
server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; max-width: 85px !important; overflow: auto;">' + motd + '</div>' + "<br />"; server_infos = server_infos + '<div id="desc_id" style="word-wrap: break-word; max-width: 85px !important; overflow: auto;">' + motd + '</div>' + "<br />";

View File

@ -44,9 +44,14 @@
</td> </td>
<td id="server_motd_{{ server['stats']['server_id']['server_id'] }}"> <td id="server_motd_{{ server['stats']['server_id']['server_id'] }}">
{% if server['stats']['desc'] != 'False' %} {% if server['stats']['desc'] != 'False' %}
<img src="/static/assets/images/pack.png" alt="icon" style="-webkit-filter:grayscale(100%); filter:grayscale(100%)" /> <div class="row">
<span id="input_motd_{{ server['stats']['server_id']['server_id'] }}" class="input_motd">{{ <div class="col-auto">
server['stats']['desc'] }}</span> <br /> <img src="/static/assets/images/pack.png" alt="icon" style="-webkit-filter:grayscale(100%); filter:grayscale(100%)" />
</div>
<div class="col-auto">
<span id="input_motd_{{ server['stats']['server_id']['server_id'] }}" class="input_motd">{{ server['stats']['desc'] }}</span>
</div>
</div>
{% end %} {% end %}
</td> </td>
<td id="server_version_{{ server['stats']['server_id']['server_id'] }}"> <td id="server_version_{{ server['stats']['server_id']['server_id'] }}">
@ -183,7 +188,7 @@
m_server_online_status = document.getElementById('m_server_online_status_' + server.id); m_server_online_status = document.getElementById('m_server_online_status_' + server.id);
/* TODO Update each element */ /* TODO Update each element */
if (server.int_ping_results) { if (server.running) {
/* Update Players */ /* Update Players */
if (server.players) { if (server.players) {
server_players.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}<br />` server_players.innerHTML = server.online + ` / ` + server.max + ` {{ translate('dashboard', 'max', data['lang']) }}<br />`
@ -193,16 +198,18 @@
var motd = ""; var motd = "";
if (server.desc) { if (server.desc) {
if (server.icon) { if (server.icon) {
motd = `<img src="data:image/png;base64,` + server.icon + `" alt="icon" /> `; img_motd = `<img src="data:image/png;base64,` + server.icon + `" alt="icon" /> `;
m_motd = `<img src="data:image/png;base64,` + server.icon + `" alt="icon" /> `; m_motd = `<img src="data:image/png;base64,` + server.icon + `" alt="icon" /> `;
} }
else { else {
motd = `<img src="/static/assets/images/pack.png" alt="icon" /> `; img_motd = `<img src="/static/assets/images/pack.png" alt="icon" /> `;
m_motd = `<img class="w-25 mr-3" src="/static/assets/images/pack.png" alt="icon" /> `; m_motd = `<img class="w-25 mr-3" src="/static/assets/images/pack.png" alt="icon" /> `;
} }
motd = motd + `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span> <br />`; desc_motd = `<span id="input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span> <br />`;
m_motd = m_motd + `<div class="media-body"><span id="m_input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span></div>`; m_motd = m_motd + `<div class="media-body"><span id="m_input_motd_` + server.id + `" class="input_motd">` + server.desc + `</span></div>`;
motd = `<div class="row"><div class="col-auto">` + img_motd + `</div><div class="col-auto">` + desc_motd + `</div></div>`;
server_motd.innerHTML = motd; server_motd.innerHTML = motd;
m_server_motd.innerHTML = m_motd; m_server_motd.innerHTML = m_motd;
} }
@ -235,17 +242,31 @@
} }
function update_servers_status(data) { function update_servers_status(data) {
console.log(data); console.log("update servers");
update_one_server_status(data[0]); data.forEach(server => {
console.log(server);
update_one_server_status(server);
});
display_motd(); display_motd();
} }
function refreshStatus() {
let xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
var myData = JSON.parse(this.responseText);
update_servers_status(myData.data);
}
};
xmlHttp.open('GET', '/api/v2/servers/status', true);
xmlHttp.send();
setTimeout(refreshStatus, 30000);
}
$(document).ready(function () { $(document).ready(function () {
console.log("ready!"); console.log("ready!");
refreshStatus();
if (webSocket) {
webSocket.on('update_server_status', update_servers_status);
}
}()); }());
</script> </script>

View File

@ -55,120 +55,7 @@
<script src="/static/assets/js/shared/hoverable-collapse.js"></script> <script src="/static/assets/js/shared/hoverable-collapse.js"></script>
<script src="/static/assets/js/shared/misc.js"></script> <script src="/static/assets/js/shared/misc.js"></script>
<script>
/* Script for WebSockets */
let usingWebSockets = false;
let webSocket = null;
let websocketTimeoutId = null;
// {% if request.protocol == 'https' %}
usingWebSockets = true;
let listenEvents = [];
let wsOpen = false;
/**
* @type {number | null} reconnectorId An interval ID for the reconnector.
*/
let reconnectorId = null;
let failedConnectionCounter = 0; // https://stackoverflow.com/a/37038217/15388424
const wsPageQueryParams = 'page_query_params=' + encodeURIComponent(location.search)
const wsPage = 'page=' + encodeURIComponent(location.pathname)
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'
)
function startWebSocket() {
console.log('%c[Crafty Controller] %cConnecting the WebSocket', 'font-weight: 900; color: #800080;', 'font-weight: 900; color: #eee;');
try {
var wsInternal = new WebSocket('wss://' + location.host + '/ws/public?' + wsPage + '&' + wsPageQueryParams);
wsInternal.onopen = function () {
console.log('opened WebSocket connection:', wsInternal)
wsOpen = true;
failedConnectionCounter = 0;
if (typeof reconnectorId === 'number') {
document.querySelectorAll('.wssError').forEach(el => el.remove())
clearInterval(reconnectorId);
reconnectorId = null;
}
};
wsInternal.onmessage = function (rawMessage) {
var message = JSON.parse(rawMessage.data);
console.log('got message: ', message)
listenEvents
.filter(listenedEvent => listenedEvent.event == message.event)
.forEach(listenedEvent => listenedEvent.callback(message.data))
};
wsInternal.onerror = function (errorEvent) {
console.error('WebSocket Error', errorEvent);
};
wsInternal.onclose = function (closeEvent) {
wsOpen = false;
console.log('Closed WebSocket', closeEvent);
if (!document.hidden) {
if (typeof reconnectorId !== 'number') {
setTimeout(sendWssError, 7000);
}
console.info("Reconnecting with a timeout of", (getRandomArbitrary(0, 2 ** failedConnectionCounter - 1) + 5) * 1000, "milliseconds");
// Discard old websocket and create a new one in 5 seconds
wsInternal = null
reconnectorId = setTimeout(startWebSocket, (getRandomArbitrary(0, 2 ** failedConnectionCounter - 1) + 5) * 1000)
failedConnectionCounter++;
}
};
webSocket = {
on: function (event, callback) {
console.log('registered ' + event + ' event');
listenEvents.push({ event: event, callback: callback })
},
emit: function (event, data) {
var message = {
event: event,
data: data
}
wsInternal.send(JSON.stringify(message));
},
close: function (code, reason) {
wsInternal.close(code, reason);
},
getStatus: function () {
return wsInternal.readyState;
}
}
} catch (error) {
console.error('Error while making websocket helpers', error);
usingWebSockets = false;
}
}
startWebSocket();
// {% else %}
warn('WebSockets are not supported in Crafty if not using the https protocol')
// {% end%}
// Managing Connexions for Multi Tab opened to reduce bandwith usage
document.addEventListener("visibilitychange", () => {
if (document.visibilityState == "hidden") {
websocketTimeoutId = setTimeout(() => {
webSocket.close(1000, "Closed due to Inactivity");
console.log('%c[Crafty Controller] %cClose Websocket due to Tab not active after 5s', 'font-weight: 900; color: #800080;', 'font-weight: 900; color: #eee;');
}, 10000);
} else {
clearTimeout(websocketTimeoutId)
if (webSocket.getStatus() == WebSocket.CLOSED) {
startWebSocket();
}
}
});
</script>
<!-- endinject --> <!-- endinject -->
{% block js %} {% block js %}
<!-- Custom js for this page --> <!-- Custom js for this page -->

View File

@ -0,0 +1,16 @@
# Generated by database migrator
import peewee
def migrate(migrator, database, **kwargs):
migrator.add_columns("server_stats", icon=peewee.CharField(null=True))
"""
Write your migrations here.
"""
def rollback(migrator, database, **kwargs):
migrator.drop_columns("server_stats", ["icon"])
"""
Write your rollback migrations here.
"""