mirror of
https://gitlab.com/crafty-controller/crafty-4.git
synced 2024-08-30 18:23:09 +00:00
Merge branch 'dev-Silversthorn' of gitlab.com:crafty-controller/crafty-commander into dev-Silversthorn
This commit is contained in:
commit
b7802fdc45
@ -1,9 +1,12 @@
|
||||
from app.classes.shared.helpers import Helpers
|
||||
import struct
|
||||
import socket
|
||||
import base64
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
import logging.config
|
||||
from app.classes.shared.console import console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -25,8 +28,26 @@ class Server:
|
||||
description = self.description
|
||||
if 'extra' in description.keys():
|
||||
for e in description['extra']:
|
||||
#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 "obfuscated" in e.keys():
|
||||
lines.append(get_code_format("obfuscated"))
|
||||
if "color" in e.keys():
|
||||
lines.append(get_code_format(e['color']))
|
||||
#Then append the text
|
||||
if "text" in e.keys():
|
||||
lines.append(e['text'])
|
||||
if e['text'] == '\n':
|
||||
lines.append("§§")
|
||||
else:
|
||||
lines.append(e['text'])
|
||||
|
||||
total_text = " ".join(lines)
|
||||
self.description = total_text
|
||||
@ -70,6 +91,26 @@ class Player:
|
||||
def __str__(self):
|
||||
return self.name
|
||||
|
||||
def get_code_format(format_name):
|
||||
root_dir = os.path.abspath(os.path.curdir)
|
||||
format_file = os.path.join(root_dir, 'app', 'config', 'motd_format.json')
|
||||
try:
|
||||
with open(format_file, "r", encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
|
||||
if format_name in data.keys():
|
||||
return data.get(format_name)
|
||||
else:
|
||||
logger.error("Format MOTD Error: format name {} does not exist".format(format_name))
|
||||
console.error("Format MOTD Error: format name {} does not exist".format(format_name))
|
||||
return ""
|
||||
|
||||
except Exception as e:
|
||||
logger.critical("Config File Error: Unable to read {} due to {}".format(format_file, e))
|
||||
console.critical("Config File Error: Unable to read {} due to {}".format(format_file, e))
|
||||
|
||||
return ""
|
||||
|
||||
|
||||
# For the rest of requests see wiki.vg/Protocol
|
||||
def ping(ip, port):
|
||||
|
@ -19,7 +19,7 @@ class ServerProps:
|
||||
s = line
|
||||
s1 = s[:s.find('=')]
|
||||
if '\n' in s:
|
||||
s2 = s[s.find('=')+1:s.find('\\')]
|
||||
s2 = s[s.find('=')+1:s.find('\n')]
|
||||
else:
|
||||
s2 = s[s.find('=')+1:]
|
||||
d[s1] = s2
|
||||
|
@ -11,6 +11,7 @@ from app.classes.shared.helpers import helper
|
||||
from app.classes.shared.console import console
|
||||
from app.classes.shared.models import Servers
|
||||
from app.classes.minecraft.server_props import ServerProps
|
||||
from app.classes.web.websocket_helper import websocket_helper
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -173,11 +174,11 @@ class ServerJars:
|
||||
response = self._get_api_result(url)
|
||||
return response
|
||||
|
||||
def download_jar(self, server, version, path):
|
||||
update_thread = threading.Thread(target=self.a_download_jar, daemon=True, name="exe_download", args=(server, version, path))
|
||||
def download_jar(self, server, version, path, name):
|
||||
update_thread = threading.Thread(target=self.a_download_jar, daemon=True, name="exe_download", args=(server, version, path, name))
|
||||
update_thread.start()
|
||||
|
||||
def a_download_jar(self, server, version, path):
|
||||
def a_download_jar(self, server, version, path, name):
|
||||
fetch_url = "{base}/api/fetchJar/{server}/{version}".format(base=self.base_url, server=server, version=version)
|
||||
|
||||
# open a file stream
|
||||
@ -189,6 +190,8 @@ class ServerJars:
|
||||
except Exception as e:
|
||||
logger.error("Unable to save jar to {path} due to error:{error}".format(path=path, error=e))
|
||||
pass
|
||||
websocket_helper.broadcast('notification', "Executable download finished for server named: " + name)
|
||||
|
||||
|
||||
return False
|
||||
|
||||
|
@ -4,6 +4,7 @@ import time
|
||||
import psutil
|
||||
import logging
|
||||
import datetime
|
||||
import base64
|
||||
|
||||
|
||||
from app.classes.shared.helpers import helper
|
||||
@ -145,12 +146,19 @@ class Stats:
|
||||
logger.info("Unable to read json from ping_obj: {}".format(e))
|
||||
pass
|
||||
|
||||
try:
|
||||
server_icon = base64.encodebytes(ping_obj.icon)
|
||||
except Exception as e:
|
||||
server_icon = False
|
||||
logger.info("Unable to read the server icon : {}".format(e))
|
||||
|
||||
ping_data = {
|
||||
'online': online_stats.get("online", 0),
|
||||
'max': online_stats.get('max', 0),
|
||||
'players': online_stats.get('players', 0),
|
||||
'server_description': ping_obj.description,
|
||||
'server_version': ping_obj.version
|
||||
'server_version': ping_obj.version,
|
||||
'server_icon': server_icon
|
||||
}
|
||||
|
||||
return ping_data
|
||||
@ -167,7 +175,7 @@ class Stats:
|
||||
|
||||
|
||||
# TODO: search server properties file for possible override of 127.0.0.1
|
||||
internal_ip = server_data.get('server-ip', "127.0.0.1")
|
||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
||||
server_port = server_settings.get('server-port', "25565")
|
||||
|
||||
logger.debug("Pinging {} on port {}".format(internal_ip, server_port))
|
||||
@ -210,7 +218,7 @@ class Stats:
|
||||
p_stats = self._get_process_stats(server_obj.PID)
|
||||
|
||||
# TODO: search server properties file for possible override of 127.0.0.1
|
||||
internal_ip = server_data.get('server-ip', "127.0.0.1")
|
||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
||||
server_port = server_settings.get('server-port', "25565")
|
||||
|
||||
logger.debug("Pinging server '{}' on {}:{}".format(s.get('server_name', "ID#{}".format(server_id)), internal_ip, server_port))
|
||||
@ -246,6 +254,62 @@ class Stats:
|
||||
server_stats_list.append(server_stats)
|
||||
|
||||
return server_stats_list
|
||||
|
||||
def get_raw_server_stats(self, server_id):
|
||||
|
||||
server_stats = {}
|
||||
server = self.controller.get_server_obj(server_id)
|
||||
|
||||
logger.debug('Getting stats for server: {}'.format(server_id))
|
||||
|
||||
# get our server object, settings and data dictionaries
|
||||
server_obj = self.controller.get_server_obj(server_id)
|
||||
server_obj.reload_server_settings()
|
||||
server_settings = self.controller.get_server_settings(server_id)
|
||||
server_data = self.controller.get_server_data(server_id)
|
||||
|
||||
# world data
|
||||
world_name = server_settings.get('level-name', 'Unknown')
|
||||
world_path = os.path.join(server_data.get('path', None), world_name)
|
||||
|
||||
# process stats
|
||||
p_stats = self._get_process_stats(server_obj.PID)
|
||||
|
||||
# TODO: search server properties file for possible override of 127.0.0.1
|
||||
internal_ip = server_data.get('server_ip', "127.0.0.1")
|
||||
server_port = server_settings.get('server-port', "25565")
|
||||
|
||||
logger.debug("Pinging server '{}' on {}:{}".format(server.name, internal_ip, server_port))
|
||||
int_mc_ping = ping(internal_ip, int(server_port))
|
||||
|
||||
int_data = False
|
||||
ping_data = {}
|
||||
|
||||
# if we got a good ping return, let's parse it
|
||||
if int_mc_ping:
|
||||
int_data = True
|
||||
ping_data = self.parse_server_ping(int_mc_ping)
|
||||
|
||||
server_stats = {
|
||||
'id': server_id,
|
||||
'started': server_obj.get_start_time(),
|
||||
'running': server_obj.check_running(),
|
||||
'cpu': p_stats.get('cpu_usage', 0),
|
||||
'mem': p_stats.get('memory_usage', 0),
|
||||
"mem_percent": p_stats.get('mem_percentage', 0),
|
||||
'world_name': world_name,
|
||||
'world_size': self.get_world_size(world_path),
|
||||
'server_port': server_port,
|
||||
'int_ping_results': int_data,
|
||||
'online': ping_data.get("online", False),
|
||||
"max": ping_data.get("max", False),
|
||||
'players': ping_data.get("players", False),
|
||||
'desc': ping_data.get("server_description", False),
|
||||
'version': ping_data.get("server_version", False),
|
||||
'icon': ping_data.get("server_icon", False)
|
||||
}
|
||||
|
||||
return server_stats
|
||||
|
||||
def record_stats(self):
|
||||
stats_to_send = self.get_node_stats()
|
||||
|
@ -97,6 +97,14 @@ class Controller:
|
||||
server_obj = self.get_server_obj(server_id)
|
||||
server_obj.reload_server_settings()
|
||||
|
||||
def get_server_settings(self, server_id):
|
||||
for s in self.servers_list:
|
||||
if int(s['server_id']) == int(server_id):
|
||||
return s['server_settings']
|
||||
|
||||
logger.warning("Unable to find server object for server id {}".format(server_id))
|
||||
return False
|
||||
|
||||
def get_server_obj(self, server_id):
|
||||
for s in self.servers_list:
|
||||
if int(s['server_id']) == int(server_id):
|
||||
@ -104,6 +112,14 @@ class Controller:
|
||||
|
||||
logger.warning("Unable to find server object for server id {}".format(server_id))
|
||||
return False
|
||||
|
||||
def get_server_data(self, server_id):
|
||||
for s in self.servers_list:
|
||||
if int(s['server_id']) == int(server_id):
|
||||
return s['server_data_obj']
|
||||
|
||||
logger.warning("Unable to find server object for server id {}".format(server_id))
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def list_defined_servers():
|
||||
@ -184,14 +200,6 @@ class Controller:
|
||||
server_list = db_helper.get_authorized_servers(userId)
|
||||
return server_list
|
||||
|
||||
def get_server_data(self, server_id):
|
||||
for s in self.servers_list:
|
||||
if int(s['server_id']) == int(server_id):
|
||||
return s['server_data_obj']
|
||||
|
||||
logger.warning("Unable to find server object for server id {}".format(server_id))
|
||||
return False
|
||||
|
||||
def list_running_servers(self):
|
||||
running_servers = []
|
||||
|
||||
@ -297,7 +305,7 @@ class Controller:
|
||||
server_stop = "stop"
|
||||
|
||||
# download the jar
|
||||
server_jar_obj.download_jar(server, version, full_jar_path)
|
||||
server_jar_obj.download_jar(server, version, full_jar_path, name)
|
||||
|
||||
new_id = self.register_server(name, server_id, server_dir, backup_path, server_command, server_file, server_log_file, server_stop)
|
||||
return new_id
|
||||
|
@ -321,7 +321,7 @@ class db_shortcuts:
|
||||
def get_all_defined_servers():
|
||||
query = Servers.select()
|
||||
return db_helper.return_rows(query)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_authorized_servers(user_id):
|
||||
server_data = []
|
||||
@ -408,7 +408,7 @@ class db_shortcuts:
|
||||
|
||||
for u in user_roles:
|
||||
roles_list.append(db_helper.get_role(u.role_id))
|
||||
|
||||
|
||||
for r in roles_list:
|
||||
role_test = Role_Servers.select().where(Role_Servers.role_id == r.get('role_id'))
|
||||
for t in role_test:
|
||||
@ -436,7 +436,7 @@ class db_shortcuts:
|
||||
if not db_helper.get_server_data_by_id(server_id):
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@staticmethod
|
||||
def server_id_authorized(serverId, user_id):
|
||||
authorized = 0
|
||||
@ -449,7 +449,7 @@ class db_shortcuts:
|
||||
if authorized.count() == 0:
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
@staticmethod
|
||||
def set_update(server_id, value):
|
||||
try:
|
||||
@ -485,16 +485,16 @@ class db_shortcuts:
|
||||
|
||||
@staticmethod
|
||||
def get_crafty_permissions_list(user_id):
|
||||
permissions_mask = db_helper.get_crafty_permissions_mask(user_id)
|
||||
permissions_mask = db_helper.get_crafty_permissions_mask(user_id)
|
||||
permissions_list = crafty_permissions.get_permissions(permissions_mask)
|
||||
return permissions_list
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_all_permission_quantity_list():
|
||||
quantity_list = {
|
||||
Enum_Permissions_Crafty.Server_Creation.name: -1,
|
||||
Enum_Permissions_Crafty.User_Config.name: -1,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: -1,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: -1,
|
||||
}
|
||||
return quantity_list
|
||||
|
||||
@ -504,7 +504,7 @@ class db_shortcuts:
|
||||
quantity_list = {
|
||||
Enum_Permissions_Crafty.Server_Creation.name: user_crafty.limit_server_creation,
|
||||
Enum_Permissions_Crafty.User_Config.name: user_crafty.limit_user_creation,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.limit_role_creation,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.limit_role_creation,
|
||||
}
|
||||
return quantity_list
|
||||
|
||||
@ -516,7 +516,7 @@ class db_shortcuts:
|
||||
try:
|
||||
user_crafty = User_Crafty.select().where(User_Crafty.user_id == user_id).get()
|
||||
except User_Crafty.DoesNotExist:
|
||||
user_crafty = User_Crafty.Insert({
|
||||
user_crafty = User_Crafty.insert({
|
||||
User_Crafty.user_id: user_id,
|
||||
User_Crafty.permissions: "000",
|
||||
User_Crafty.limit_server_creation: 0,
|
||||
@ -540,16 +540,16 @@ class db_shortcuts:
|
||||
quantity_list = {
|
||||
Enum_Permissions_Crafty.Server_Creation.name: user_crafty.created_server,
|
||||
Enum_Permissions_Crafty.User_Config.name: user_crafty.created_user,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.created_role,
|
||||
Enum_Permissions_Crafty.Roles_Config.name: user_crafty.created_role,
|
||||
}
|
||||
return quantity_list
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_crafty_limit_value(user_id, permission):
|
||||
user_crafty = db_helper.get_User_Crafty(user_id)
|
||||
quantity_list = get_permission_quantity_list(user_id)
|
||||
return quantity_list[permission]
|
||||
|
||||
|
||||
@staticmethod
|
||||
def can_add_in_crafty(user_id, permission):
|
||||
user_crafty = db_helper.get_User_Crafty(user_id)
|
||||
@ -559,16 +559,20 @@ class db_shortcuts:
|
||||
return can and ((quantity_list[permission.name] < limit_list[permission.name]) or limit_list[permission.name] == -1 )
|
||||
|
||||
@staticmethod
|
||||
def add_server_creation(user_id):
|
||||
def add_server_creation(user_id):
|
||||
user_crafty = db_helper.get_User_Crafty(user_id)
|
||||
user_crafty.created_server += 1
|
||||
User_Crafty.save(user_crafty)
|
||||
return user_crafty.created_server
|
||||
<<<<<<< HEAD
|
||||
|
||||
|
||||
#************************************************************************************************
|
||||
# Host_Stats Methods
|
||||
#************************************************************************************************
|
||||
=======
|
||||
|
||||
>>>>>>> 45739a2e5ffd23d2373c51a4e5122e73ea174359
|
||||
@staticmethod
|
||||
def get_latest_hosts_stats():
|
||||
query = Host_Stats.select().order_by(Host_Stats.id.desc()).get()
|
||||
@ -611,7 +615,48 @@ class db_shortcuts:
|
||||
return user
|
||||
else:
|
||||
return {}
|
||||
<<<<<<< HEAD
|
||||
|
||||
=======
|
||||
|
||||
@staticmethod
|
||||
def add_role_to_user(user_id, role_id):
|
||||
User_Roles.insert({
|
||||
User_Roles.user_id: user_id,
|
||||
User_Roles.role_id: role_id
|
||||
}).execute()
|
||||
|
||||
@staticmethod
|
||||
def add_user_roles(user):
|
||||
if type(user) == dict:
|
||||
user_id = user['user_id']
|
||||
else:
|
||||
user_id = user.user_id
|
||||
|
||||
# I just copied this code from get_user, it had those TODOs & comments made by mac - Lukas
|
||||
|
||||
roles_query = User_Roles.select().join(Roles, JOIN.INNER).where(User_Roles.user_id == user_id)
|
||||
# TODO: this query needs to be narrower
|
||||
roles = set()
|
||||
for r in roles_query:
|
||||
roles.add(r.role_id.role_id)
|
||||
|
||||
user['roles'] = roles
|
||||
#logger.debug("user: ({}) {}".format(user_id, user))
|
||||
return user
|
||||
|
||||
@staticmethod
|
||||
def add_user_crafty(user_id, uc_permissions):
|
||||
user_crafty = User_Crafty.insert({User_Crafty.user_id: user_id, User_Crafty.permissions: uc_permissions}).execute()
|
||||
return user_crafty
|
||||
|
||||
@staticmethod
|
||||
def add_role_server(server_id, role_id, rs_permissions="00000000"):
|
||||
servers = Role_Servers.insert({Role_Servers.server_id: server_id, Role_Servers.role_id: role_id, Role_Servers.permissions: rs_permissions}).execute()
|
||||
return servers
|
||||
|
||||
|
||||
>>>>>>> 45739a2e5ffd23d2373c51a4e5122e73ea174359
|
||||
@staticmethod
|
||||
def user_query(user_id):
|
||||
user_query = Users.select().where(Users.user_id == user_id)
|
||||
@ -937,7 +982,7 @@ class db_shortcuts:
|
||||
Audit_Log.log_msg: audit_msg,
|
||||
Audit_Log.source_ip: source_ip
|
||||
}).execute()
|
||||
|
||||
|
||||
@staticmethod
|
||||
def add_to_audit_log_raw(user_name, user_id, server_id, log_msg, source_ip):
|
||||
Audit_Log.insert({
|
||||
@ -1082,7 +1127,7 @@ class Permissions_Servers:
|
||||
for member in Enum_Permissions_Server.__members__.items():
|
||||
permissions_list.append(member[1])
|
||||
return permissions_list
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_permissions(permissions_mask):
|
||||
permissions_list = []
|
||||
@ -1097,17 +1142,17 @@ class Permissions_Servers:
|
||||
if permission_mask[permission_tested.value] == '1':
|
||||
result = True
|
||||
return result
|
||||
|
||||
|
||||
@staticmethod
|
||||
def set_permission(permission_mask, permission_tested: Enum_Permissions_Server, value):
|
||||
l = list(permission_mask)
|
||||
l[permission_tested.value] = str(value)
|
||||
permission_mask = ''.join(l)
|
||||
return permission_mask
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_permission(permission_mask, permission_tested: Enum_Permissions_Server):
|
||||
return permission_mask[permission_tested.value]
|
||||
return permission_mask[permission_tested.value]
|
||||
|
||||
#************************************************************************************************
|
||||
# Crafty Permissions Class
|
||||
@ -1116,7 +1161,7 @@ class Enum_Permissions_Crafty(Enum):
|
||||
Server_Creation = 0
|
||||
User_Config = 1
|
||||
Roles_Config = 2
|
||||
|
||||
|
||||
class Permissions_Crafty:
|
||||
|
||||
@staticmethod
|
||||
@ -1125,7 +1170,7 @@ class Permissions_Crafty:
|
||||
for member in Enum_Permissions_Crafty.__members__.items():
|
||||
permissions_list.append(member[1])
|
||||
return permissions_list
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_permissions(permissions_mask):
|
||||
permissions_list = []
|
||||
@ -1140,17 +1185,17 @@ class Permissions_Crafty:
|
||||
if permission_mask[permission_tested.value] == '1':
|
||||
result = True
|
||||
return result
|
||||
|
||||
|
||||
@staticmethod
|
||||
def set_permission(permission_mask, permission_tested: Enum_Permissions_Crafty, value):
|
||||
l = list(permission_mask)
|
||||
l[permission_tested.value] = str(value)
|
||||
permission_mask = ''.join(l)
|
||||
return permission_mask
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_permission(permission_mask, permission_tested: Enum_Permissions_Crafty):
|
||||
return permission_mask[permission_tested.value]
|
||||
return permission_mask[permission_tested.value]
|
||||
|
||||
|
||||
#************************************************************************************************
|
||||
@ -1159,4 +1204,4 @@ class Permissions_Crafty:
|
||||
installer = db_builder()
|
||||
db_helper = db_shortcuts()
|
||||
server_permissions = Permissions_Servers()
|
||||
crafty_permissions = Permissions_Crafty()
|
||||
crafty_permissions = Permissions_Crafty()
|
||||
|
@ -115,7 +115,6 @@ class Server:
|
||||
self.settings = server_data_obj
|
||||
|
||||
# build our server run command
|
||||
self.setup_server_run_command()
|
||||
|
||||
if server_data_obj['auto_start']:
|
||||
delay = int(self.settings['auto_start_delay'])
|
||||
|
55
app/classes/web/status_handler.py
Normal file
55
app/classes/web/status_handler.py
Normal file
@ -0,0 +1,55 @@
|
||||
from re import template
|
||||
import sys
|
||||
import json
|
||||
import logging
|
||||
import tornado.web
|
||||
import tornado.escape
|
||||
import requests
|
||||
|
||||
from app.classes.shared.helpers import helper
|
||||
from app.classes.web.base_handler import BaseHandler
|
||||
from app.classes.shared.console import console
|
||||
from app.classes.shared.models import Users, fn, db_helper
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
try:
|
||||
import bleach
|
||||
|
||||
except ModuleNotFoundError as e:
|
||||
logger.critical("Import Error: Unable to load {} module".format(e.name), exc_info=True)
|
||||
console.critical("Import Error: Unable to load {} module".format(e.name))
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class StatusHandler(BaseHandler):
|
||||
def get(self):
|
||||
page_data = {}
|
||||
page_data['servers'] = db_helper.get_all_servers_stats()
|
||||
for srv in page_data['servers']:
|
||||
server_data = srv.get('server_data', False)
|
||||
server_id = server_data.get('server_id', False)
|
||||
srv['raw_ping_result'] = self.controller.stats.get_raw_server_stats(server_id)
|
||||
|
||||
template = 'public/status.html'
|
||||
|
||||
self.render(
|
||||
template,
|
||||
data=page_data,
|
||||
translate=self.translator.translate,
|
||||
)
|
||||
def post(self):
|
||||
page_data = {}
|
||||
page_data['servers'] = db_helper.get_all_servers_stats()
|
||||
for srv in page_data['servers']:
|
||||
server_data = srv.get('server_data', False)
|
||||
server_id = server_data.get('server_id', False)
|
||||
srv['raw_ping_result'] = self.controller.stats.get_raw_server_stats(server_id)
|
||||
|
||||
template = 'public/status.html'
|
||||
|
||||
self.render(
|
||||
template,
|
||||
data=page_data,
|
||||
translate=self.translator.translate,
|
||||
)
|
@ -29,6 +29,7 @@ try:
|
||||
from app.classes.shared.translation import translation
|
||||
from app.classes.web.upload_handler import UploadHandler
|
||||
from app.classes.web.http_handler import HTTPHandler, HTTPHandlerPage
|
||||
from app.classes.web.status_handler import StatusHandler
|
||||
|
||||
except ModuleNotFoundError as e:
|
||||
logger.critical("Import Error: Unable to load {} module".format(e, e.name))
|
||||
@ -132,6 +133,7 @@ class Webserver:
|
||||
(r'/api/stats/node', NodeStats, handler_args),
|
||||
(r'/ws', SocketHandler, handler_args),
|
||||
(r'/upload', UploadHandler),
|
||||
(r'/status', StatusHandler, handler_args)
|
||||
]
|
||||
|
||||
app = tornado.web.Application(
|
||||
|
@ -80,3 +80,8 @@ body { background-color: var(--dark) !important; /* Firefox */ }
|
||||
.actions_serverlist > a > i {
|
||||
cursor: pointer;
|
||||
}
|
||||
.corner {
|
||||
position: absolute;
|
||||
margin-top: 0;
|
||||
margin-left: 0;
|
||||
}
|
BIN
app/frontend/static/assets/images/logo_long.png
Normal file
BIN
app/frontend/static/assets/images/logo_long.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
BIN
app/frontend/static/assets/images/pack.png
Normal file
BIN
app/frontend/static/assets/images/pack.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 25 KiB |
127
app/frontend/static/assets/js/motd.js
Normal file
127
app/frontend/static/assets/js/motd.js
Normal file
@ -0,0 +1,127 @@
|
||||
var obfuscators = [];
|
||||
var styleMap = {
|
||||
'§0': 'color:#000000',
|
||||
'§1': 'color:#0000AA',
|
||||
'§2': 'color:#00AA00',
|
||||
'§3': 'color:#00AAAA',
|
||||
'§4': 'color:#AA0000',
|
||||
'§5': 'color:#AA00AA',
|
||||
'§6': 'color:#FFAA00',
|
||||
'§7': 'color:#AAAAAA',
|
||||
'§8': 'color:#555555',
|
||||
'§9': 'color:#5555FF',
|
||||
'§a': 'color:#55FF55',
|
||||
'§b': 'color:#55FFFF',
|
||||
'§c': 'color:#FF5555',
|
||||
'§d': 'color:#FF55FF',
|
||||
'§e': 'color:#FFFF55',
|
||||
'§f': 'color:#FFFFFF',
|
||||
'§l': 'font-weight:bold',
|
||||
'§m': 'text-decoration:line-through',
|
||||
'§n': 'text-decoration:underline',
|
||||
'§o': 'font-style:italic',
|
||||
};
|
||||
function obfuscate(string, elem) {
|
||||
var magicSpan,
|
||||
currNode;
|
||||
if(string.indexOf('<br>') > -1) {
|
||||
elem.innerHTML = string;
|
||||
for(var j = 0, len = elem.childNodes.length; j < len; j++) {
|
||||
currNode = elem.childNodes[j];
|
||||
if(currNode.nodeType === 3) {
|
||||
magicSpan = document.createElement('span');
|
||||
magicSpan.innerHTML = currNode.nodeValue;
|
||||
elem.replaceChild(magicSpan, currNode);
|
||||
init(magicSpan);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
init(elem, string);
|
||||
}
|
||||
function init(el, str) {
|
||||
var i = 0,
|
||||
obsStr = str || el.innerHTML,
|
||||
len = obsStr.length;
|
||||
obfuscators.push( window.setInterval(function () {
|
||||
if(i >= len) i = 0;
|
||||
obsStr = replaceRand(obsStr, i);
|
||||
el.innerHTML = obsStr;
|
||||
i++;
|
||||
}, 0) );
|
||||
}
|
||||
function randInt(min, max) {
|
||||
return Math.floor( Math.random() * (max - min + 1) ) + min;
|
||||
}
|
||||
function replaceRand(string, i) {
|
||||
var randChar = String.fromCharCode( randInt(64, 95) );
|
||||
return string.substr(0, i) + randChar + string.substr(i + 1, string.length);
|
||||
}
|
||||
}
|
||||
function applyCode(string, codes) {
|
||||
var elem = document.createElement('span'),
|
||||
obfuscated = false;
|
||||
string = string.replace(/\x00*/g, '');
|
||||
for(var i = 0, len = codes.length; i < len; i++) {
|
||||
elem.style.cssText += styleMap[codes[i]] + ';';
|
||||
if(codes[i] === '§k') {
|
||||
obfuscate(string, elem);
|
||||
obfuscated = true;
|
||||
}
|
||||
}
|
||||
if(!obfuscated) elem.innerHTML = string;
|
||||
return elem;
|
||||
}
|
||||
function parseStyle(string) {
|
||||
var codes = string.match(/§.{1}/g) || [],
|
||||
indexes = [],
|
||||
apply = [],
|
||||
tmpStr,
|
||||
deltaIndex,
|
||||
noCode,
|
||||
final = document.createDocumentFragment(),
|
||||
i;
|
||||
string = string.replace(/\n|\\n/g, '<br>');
|
||||
for(i = 0, len = codes.length; i < len; i++) {
|
||||
indexes.push( string.indexOf(codes[i]) );
|
||||
string = string.replace(codes[i], '\x00\x00');
|
||||
}
|
||||
if(indexes[0] !== 0) {
|
||||
final.appendChild( applyCode( string.substring(0, indexes[0]), [] ) );
|
||||
}
|
||||
for(i = 0; i < len; i++) {
|
||||
indexDelta = indexes[i + 1] - indexes[i];
|
||||
if(indexDelta === 2) {
|
||||
while(indexDelta === 2) {
|
||||
apply.push ( codes[i] );
|
||||
i++;
|
||||
indexDelta = indexes[i + 1] - indexes[i];
|
||||
}
|
||||
apply.push ( codes[i] );
|
||||
} else {
|
||||
apply.push( codes[i] );
|
||||
}
|
||||
if( apply.lastIndexOf('§r') > -1) {
|
||||
apply = apply.slice( apply.lastIndexOf('§r') + 1 );
|
||||
}
|
||||
tmpStr = string.substring( indexes[i], indexes[i + 1] );
|
||||
final.appendChild( applyCode(tmpStr, apply) );
|
||||
}
|
||||
return final;
|
||||
}
|
||||
function clearObfuscators() {
|
||||
var i = obfuscators.length;
|
||||
for(;i--;) {
|
||||
clearInterval(obfuscators[i]);
|
||||
}
|
||||
obfuscators = [];
|
||||
}
|
||||
function initParser(input, output) {
|
||||
clearObfuscators();
|
||||
var input = document.getElementById(input),
|
||||
output = document.getElementById(output);
|
||||
if (input != null && output != null) {
|
||||
var parsed = parseStyle( input.innerHTML );
|
||||
output.innerHTML = '';
|
||||
output.appendChild(parsed);
|
||||
}
|
||||
}
|
@ -11,6 +11,8 @@
|
||||
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/fontawesome5/css/all.css">
|
||||
<link rel="stylesheet" href="/static/assest/css/crafty.css">
|
||||
<!-- endinject -->
|
||||
<!-- Plugin css for this page -->
|
||||
<!-- End Plugin css for this page -->
|
||||
@ -24,7 +26,7 @@
|
||||
<div class="container-fluid page-body-wrapper full-page-wrapper">
|
||||
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
|
||||
<div class="row w-100">
|
||||
<div class="col-lg-4 mx-auto">
|
||||
<div class="mx-auto">
|
||||
|
||||
{% block content %}
|
||||
{% end %}
|
||||
@ -47,5 +49,11 @@
|
||||
<script src="/static/assets/js/shared/settings.js"></script>
|
||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||
<!-- endinject -->
|
||||
|
||||
{% block js %}
|
||||
<!-- Custom js for this page -->
|
||||
<!-- End custom js for this page -->
|
||||
{% end %}
|
||||
|
||||
</body>
|
||||
</html>
|
@ -184,7 +184,7 @@
|
||||
</label>
|
||||
|
||||
</div>
|
||||
{% end %}
|
||||
{% end %}
|
||||
<button type="submit" class="btn btn-success mr-2"><i class="fas fa-save"></i> {{ translate('panelConfig', 'save') }}</button>
|
||||
<button type="reset" onclick="location.href='/panel/panel_config'" class="btn btn-light"><i class="fas fa-undo-alt"></i> {{ translate('panelConfig', 'cancel') }}</button>
|
||||
</form>
|
||||
|
82
app/frontend/templates/public/status.html
Normal file
82
app/frontend/templates/public/status.html
Normal file
@ -0,0 +1,82 @@
|
||||
{% extends ../public_base.html %}
|
||||
|
||||
{% block meta %}
|
||||
<meta http-equiv="refresh" content="30">
|
||||
{% end %}
|
||||
|
||||
{% block title %}Crafty Controller - {{ translate('dashboard', 'dashboard') }}{% end %}
|
||||
|
||||
{% block content %}
|
||||
<div class="content-wrapper col-md login-modal" style="background-color: #222437;">
|
||||
<img src="/static/assets/images/logo_long.png" style='width: 25%; margin-left: 38%;'>
|
||||
<hr />
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover">
|
||||
<thead>
|
||||
<tr class="rounded">
|
||||
<th>{{ translate('dashboard', 'server') }}</th>
|
||||
<th>{{ translate('dashboard', 'players') }}</th>
|
||||
<th>{{ translate('dashboard', 'motd') }}</th>
|
||||
<th>{{ translate('dashboard', 'version') }}</th>
|
||||
<th>{{ translate('dashboard', 'status') }}</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for server in data['servers'] %}
|
||||
<tr>
|
||||
<td>
|
||||
<i class="fas fa-server"></i>
|
||||
{{ server['server_data']['server_name'] }}
|
||||
</td>
|
||||
{% if server['stats']['int_ping_results'] != 'False' %}
|
||||
<td>
|
||||
{{ server['stats']['online'] }} / {{ server['stats']['max'] }} {{ translate('dashboard', 'max') }}<br />
|
||||
</td>
|
||||
<td>
|
||||
{% if server['stats']['desc'] != 'False' %}
|
||||
{% if server['raw_ping_result']['icon'] %}
|
||||
<img src="data:image/png;base64,{% raw server['raw_ping_result']['icon'] %}" alt="icon"/>
|
||||
{% else %}
|
||||
<img src="/static/assets/images/pack.png" alt="icon" />
|
||||
{% end %}
|
||||
<span id="input_motd">{{ server['stats']['desc'] }}</span> <br />
|
||||
{% end %}
|
||||
</td>
|
||||
<td>
|
||||
{% if server['stats']['version'] != 'False' %}
|
||||
{{ server['stats']['version'] }}
|
||||
{% end %}
|
||||
</td>
|
||||
{% else %}
|
||||
<td colspan="3">
|
||||
<span class="text-warning"><i class="fas fa-exclamation-triangle"></i> Crafty can't get infos from this Server </span>
|
||||
</td>
|
||||
{% end %}
|
||||
<td>
|
||||
{% if server['stats']['int_ping_results'] %}
|
||||
<span class="text-success"><i class="fas fa-signal"></i> {{ translate('dashboard', 'online') }}</span>
|
||||
{% else %}
|
||||
<span class="text-danger"><i class="fas fa-ban"></i> {{ translate('dashboard', 'offline') }}</span>
|
||||
{% end %}
|
||||
</td>
|
||||
</tr>
|
||||
{% end %}
|
||||
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<hr />
|
||||
</div>
|
||||
|
||||
{% end %}
|
||||
|
||||
{% block js %}
|
||||
|
||||
<script src="/static/assets/js/motd.js"></script>
|
||||
<script>
|
||||
$(document).ready(function () {
|
||||
initParser('input_motd', 'input_motd');
|
||||
}());
|
||||
</script>
|
||||
|
||||
{% end %}
|
59
app/frontend/templates/public_base.html
Normal file
59
app/frontend/templates/public_base.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<!-- Required meta tags -->
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
||||
{% block meta %}{% end %}
|
||||
<title>{% block title %}{{ _('Default') }}{% end %}</title>
|
||||
<!-- plugins:css -->
|
||||
<link rel="stylesheet" href="/static/assets/vendors/mdi/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/flag-icon-css/css/flag-icon.min.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/ti-icons/css/themify-icons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/typicons/typicons.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/css/vendor.bundle.base.css">
|
||||
<link rel="stylesheet" href="/static/assets/vendors/fontawesome5/css/all.css">
|
||||
<!-- endinject -->
|
||||
<!-- Plugin css for this page -->
|
||||
<!-- End Plugin css for this page -->
|
||||
<!-- Layout styles -->
|
||||
<link rel="stylesheet" href="/static/assets/css/dark/style.css">
|
||||
<!-- End Layout styles -->
|
||||
<link rel="shortcut icon" href="/static/assets/images/favicon.png" />
|
||||
</head>
|
||||
<body class="dark-theme">
|
||||
<div class="container-scroller">
|
||||
<div class="container-fluid page-body-wrapper full-page-wrapper">
|
||||
<div class="content-wrapper d-flex align-items-center auth auth-bg-1 theme-one">
|
||||
<div class="row w-100">
|
||||
<div class="mx-auto">
|
||||
<div class="auto-form-wrapper">
|
||||
{% block content %}
|
||||
{% end %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- content-wrapper ends -->
|
||||
</div>
|
||||
<!-- page-body-wrapper ends -->
|
||||
</div>
|
||||
<!-- container-scroller -->
|
||||
<!-- plugins:js -->
|
||||
<script src="/static/assets/vendors/js/vendor.bundle.base.js"></script>
|
||||
<!-- endinject -->
|
||||
<!-- inject:js -->
|
||||
<script src="/static/assets/js/shared/off-canvas.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/settings.js"></script>
|
||||
<script src="/static/assets/js/shared/todolist.js"></script>
|
||||
<!-- endinject -->
|
||||
|
||||
{% block js %}
|
||||
<!-- Custom js for this page -->
|
||||
<!-- End custom js for this page -->
|
||||
{% end %}
|
||||
|
||||
</body>
|
||||
</html>
|
@ -70,6 +70,8 @@
|
||||
"server": "Server",
|
||||
"actions": "Actions",
|
||||
"world": "World",
|
||||
"motd": "MOTD",
|
||||
"version": "Version",
|
||||
"status": "Status",
|
||||
"online": "Online",
|
||||
"offline": "Offline",
|
||||
|
@ -70,6 +70,8 @@
|
||||
"server": "Palvelin",
|
||||
"actions": "Toiminnot",
|
||||
"world": "Maailma",
|
||||
"motd": "MOTD",
|
||||
"version": "Versio",
|
||||
"status": "Tila",
|
||||
"online": "Päällä",
|
||||
"offline": "Pois päältä",
|
||||
|
@ -70,6 +70,8 @@
|
||||
"server": "Serveur",
|
||||
"actions": "Actions",
|
||||
"world": "Monde",
|
||||
"motd": "MOTD",
|
||||
"version": "Version",
|
||||
"status": "Statut",
|
||||
"online": "En Ligne",
|
||||
"offline": "Hors Ligne",
|
||||
|
Loading…
Reference in New Issue
Block a user