diff --git a/app/classes/shared/server.py b/app/classes/shared/server.py index 9dcb7646..5193dd59 100644 --- a/app/classes/shared/server.py +++ b/app/classes/shared/server.py @@ -20,6 +20,7 @@ from app.classes.models.servers import Servers, servers_helper from app.classes.models.management import management_helper from app.classes.web.websocket_helper import websocket_helper from app.classes.shared.translation import translation +from app.classes.models.users import users_helper logger = logging.getLogger(__name__) @@ -145,14 +146,14 @@ class Server: def run_scheduled_server(self): console.info("Starting server ID: {} - {}".format(self.server_id, self.name)) logger.info("Starting server {}".format(self.server_id, self.name)) - self.run_threaded_server() + self.run_threaded_server(None) # remove the scheduled job since it's ran return schedule.CancelJob - def run_threaded_server(self, lang): + def run_threaded_server(self, user_id): # start the server - self.server_thread = threading.Thread(target=self.start_server, daemon=True, args=(lang,), name='{}_server_thread'.format(self.server_id)) + self.server_thread = threading.Thread(target=self.start_server, daemon=True, args=(user_id,), name='{}_server_thread'.format(self.server_id)) self.server_thread.start() def setup_server_run_command(self): @@ -177,7 +178,11 @@ class Server: console.warning("Unable to write/access {}".format(self.server_path)) helper.do_exit() - def start_server(self, user_lang): + def start_server(self, user_id): + if not user_id: + user_lang = helper.get_setting('language') + else: + user_lang = users_helper.get_user_lang_by_id(user_id) logger.info("Start command detected. Reloading settings from DB for server {}".format(self.name)) self.setup_server_run_command() @@ -214,9 +219,14 @@ class Server: e_flag = False if e_flag == False: - websocket_helper.broadcast('send_eula_bootbox', { - 'id': self.server_id - }) + if user_id: + websocket_helper.broadcast_user(user_id, 'send_eula_bootbox', { + 'id': self.server_id + }) + else: + logger.error("Autostart failed due to EULA being false. Agree not sent due to auto start.") + servers_helper.set_waiting_start(self.server_id, False) + return False return False f.close() @@ -235,23 +245,25 @@ class Server: except Exception as ex: msg = "Server {} failed to start with error code: {}".format(self.name, ex) logger.error(msg) - websocket_helper.broadcast('send_start_error', { - 'error': translation.translate('error', 'start-error', user_lang).format(self.name, ex) - }) + if user_id: + websocket_helper.broadcast_user(user_id, 'send_start_error',{ + 'error': translation.translate('error', 'start-error', user_lang).format(self.name, ex) + }) return False - if helper.check_internet(): - loc_server_port = servers_helper.get_server_stats_by_id(self.server_id)['server_port'] - if helper.check_port(loc_server_port): - websocket_helper.broadcast('send_start_reload', { + if user_id: + if helper.check_internet(): + loc_server_port = servers_helper.get_server_stats_by_id(self.server_id)['server_port'] + if helper.check_port(loc_server_port): + websocket_helper.broadcast_user(user_id, 'send_start_reload', { + }) + else: + websocket_helper.broadcast_user(user_id, 'send_start_error', { + 'error': translation.translate('error', 'closedPort', user_lang).format(loc_server_port) }) else: - websocket_helper.broadcast('send_start_error', { - 'error': translation.translate('error', 'closedPort', user_lang).format(loc_server_port) - }) - else: - websocket_helper.broadcast('send_start_error', { - 'error': translation.translate('error', 'internet', user_lang) - }) + websocket_helper.broadcast_user(user_id, 'send_start_error', { + 'error': translation.translate('error', 'internet', user_lang) + }) servers_helper.set_waiting_start(self.server_id, False) out_buf = ServerOutBuf(self.process, self.server_id) @@ -322,15 +334,14 @@ class Server: self.stats.record_stats() - def restart_threaded_server(self, lang): - + def restart_threaded_server(self, user_id): # if not already running, let's just start if not self.check_running(): - self.run_threaded_server(lang) + self.run_threaded_server(user_id) else: self.stop_threaded_server() time.sleep(2) - self.run_threaded_server(lang) + self.run_threaded_server(user_id) def cleanup_server_object(self): self.start_time = None @@ -373,7 +384,7 @@ class Server: if self.settings['crash_detection']: logger.warning("The server {} has crashed and will be restarted. Restarting server".format(name)) console.warning("The server {} has crashed and will be restarted. Restarting server".format(name)) - self.run_threaded_server('en_EN') + self.run_threaded_server(None) return True else: logger.critical( @@ -447,12 +458,12 @@ class Server: console.info("Removing old crash detection watcher thread") schedule.clear(self.name) - def agree_eula(self, user_lang): + def agree_eula(self, user_id): file = os.path.join(self.server_path, 'eula.txt') f = open(file, 'w') f.write('eula=true') f.close - self.run_threaded_server(user_lang) + self.run_threaded_server(user_id) def is_backup_running(self): if self.is_backingup: @@ -502,11 +513,14 @@ class Server: def list_backups(self): conf = management_helper.get_backup_config(self.server_id) - if helper.check_path_exists(helper.get_os_understandable_path(self.settings['backup_path'])): - files = helper.get_human_readable_files_sizes(helper.list_dir_by_date(helper.get_os_understandable_path(self.settings['backup_path']))) - return [{"path": os.path.relpath(f['path'], start=helper.get_os_understandable_path(conf['backup_path'])), "size": f["size"]} for f in files] + if self.settings['backup_path']: + if helper.check_path_exists(helper.get_os_understandable_path(self.settings['backup_path'])): + files = helper.get_human_readable_files_sizes(helper.list_dir_by_date(helper.get_os_understandable_path(self.settings['backup_path']))) + return [{"path": os.path.relpath(f['path'], start=helper.get_os_understandable_path(conf['backup_path'])), "size": f["size"]} for f in files] + else: + return [] else: - return [] + return[] def jar_update(self): servers_helper.set_update(self.server_id, True) @@ -535,12 +549,14 @@ class Server: # There are clients self.check_update() message = ' UPDATING...' - websocket_helper.broadcast('update_button_status', { + websocket_helper.broadcast_page('/panel/server_detail', 'update_button_status', { 'isUpdating': self.check_update(), 'server_id': self.server_id, 'wasRunning': wasStarted, 'string': message }) + websocket_helper.broadcast_page('/panel/dashboard', 'send_start_reload', { + }) backup_dir = os.path.join(helper.get_os_understandable_path(self.settings['path']), 'crafty_executable_backups') #checks if backup directory already exists if os.path.isdir(backup_dir): @@ -568,7 +584,6 @@ class Server: while servers_helper.get_server_stats_by_id(self.server_id)['updating']: if downloaded and not self.is_backingup: - print("Backup Status: " + str(self.is_backingup)) logger.info("Executable updated successfully. Starting Server") servers_helper.set_update(self.server_id, False) @@ -577,11 +592,13 @@ class Server: self.check_update() websocket_helper.broadcast('notification', "Executable update finished for " + self.name) time.sleep(3) - websocket_helper.broadcast('update_button_status', { + websocket_helper.broadcast_page('/panel/server_detail', 'update_button_status', { 'isUpdating': self.check_update(), 'server_id': self.server_id, 'wasRunning': wasStarted }) + websocket_helper.broadcast_page('/panel/dashboard', 'send_start_reload', { + }) websocket_helper.broadcast('notification', "Executable update finished for "+self.name) management_helper.add_to_audit_log_raw('Alert', '-1', self.server_id, "Executable update finished for "+self.name, self.settings['server_ip']) diff --git a/app/classes/shared/tasks.py b/app/classes/shared/tasks.py index 800335b9..1ab6c05e 100644 --- a/app/classes/shared/tasks.py +++ b/app/classes/shared/tasks.py @@ -98,17 +98,17 @@ class TasksManager: for c in commands: svr = self.controller.get_server_obj(c['server_id']['server_id']) - user_lang = c.get('user')['lang'] + user_id = c.get('user')['user_id'] command = c.get('command', None) if command == 'start_server': - svr.run_threaded_server(user_lang) + svr.run_threaded_server(user_id) elif command == 'stop_server': svr.stop_threaded_server() elif command == "restart_server": - svr.restart_threaded_server(user_lang) + svr.restart_threaded_server(user_id) elif command == "backup_server": svr.backup_server() diff --git a/app/classes/web/ajax_handler.py b/app/classes/web/ajax_handler.py index 8e50b8c5..0e4c5faa 100644 --- a/app/classes/web/ajax_handler.py +++ b/app/classes/web/ajax_handler.py @@ -210,7 +210,7 @@ class AjaxHandler(BaseHandler): elif page == "eula": server_id = self.get_argument('id', None) svr = self.controller.get_server_obj(server_id) - svr.agree_eula(self.controller.users.get_user_lang_by_id(user_data['user_id'])) + svr.agree_eula(user_data['user_id']) @tornado.web.authenticated def delete(self, page): diff --git a/app/classes/web/panel_handler.py b/app/classes/web/panel_handler.py index 33abb0c5..d5e8d499 100644 --- a/app/classes/web/panel_handler.py +++ b/app/classes/web/panel_handler.py @@ -647,6 +647,12 @@ class PanelHandler(BaseHandler): return server_obj = self.controller.servers.get_server_obj(server_id) + server_settings = self.controller.get_server_data(server_id) + stale_executable = server_obj.executable + #Compares old jar name to page data being passed. If they are different we replace the executable name in the + if str(stale_executable) != str(executable): + execution_command = execution_command.replace(str(stale_executable), str(executable)) + server_obj.server_name = server_name server_obj.path = server_path server_obj.log_path = log_path @@ -693,7 +699,6 @@ class PanelHandler(BaseHandler): self.redirect("/panel/error?error=Invalid Server ID") return - if backup_path is not None: if enabled == '0': #TODO Use Controller method server_obj = self.controller.servers.get_server_obj(server_id) diff --git a/app/classes/web/websocket_handler.py b/app/classes/web/websocket_handler.py index e1c1a737..1ec54f3a 100644 --- a/app/classes/web/websocket_handler.py +++ b/app/classes/web/websocket_handler.py @@ -1,11 +1,13 @@ import json import logging import asyncio +import sys from urllib.parse import parse_qsl from app.classes.models.users import Users from app.classes.shared.helpers import helper from app.classes.web.websocket_helper import websocket_helper +from app.classes.shared.console import console logger = logging.getLogger(__name__) @@ -31,6 +33,14 @@ class SocketHandler(tornado.websocket.WebSocketHandler): self.request.remote_ip return remote_ip + def get_user_id(self): + user_data_cookie_raw = self.get_secure_cookie('user_data') + + if user_data_cookie_raw and user_data_cookie_raw.decode('utf-8'): + user_data_cookie = user_data_cookie_raw.decode('utf-8') + user_id = json.loads(user_data_cookie)['user_id'] + return user_id + def check_auth(self): user_data_cookie_raw = self.get_secure_cookie('user_data') diff --git a/app/classes/web/websocket_helper.py b/app/classes/web/websocket_helper.py index 99935ad3..916d419f 100644 --- a/app/classes/web/websocket_helper.py +++ b/app/classes/web/websocket_helper.py @@ -42,15 +42,36 @@ class WebSocketHelper: def filter_fn(client): return client.page == page - clients = list(filter(filter_fn, self.clients)) + self.broadcast_with_fn(filter_fn, event_type, data) - logger.debug('Sending to {} out of {} clients: {}'.format(len(clients), len(self.clients), json.dumps({'event': event_type, 'data': data}))) + def broadcast_user(self, user_id: str, event_type: str, data): + def filter_fn(client): + return client.get_user_id() == user_id - for client in clients: - try: - self.send_message(client, event_type, data) - except Exception as e: - logger.exception('Error catched while sending WebSocket message to {}'.format(client.get_remote_ip())) + self.broadcast_with_fn(filter_fn, event_type, data) + + def broadcast_user_page(self, page: str, user_id: str, event_type: str, data): + def filter_fn(client): + if client.get_user_id() != user_id: + return False + if client.page != page: + return False + return True + + self.broadcast_with_fn(filter_fn, event_type, data) + + def broadcast_user_page_params(self, page: str, params: dict, user_id: str, event_type: str, data): + def filter_fn(client): + if client.get_user_id() != user_id: + return False + if client.page != page: + return False + for key, param in params.items(): + if param != client.page_query_params.get(key, None): + return False + return True + + self.broadcast_with_fn(filter_fn, event_type, data) def broadcast_page_params(self, page: str, params: dict, event_type: str, data): def filter_fn(client): @@ -61,6 +82,9 @@ class WebSocketHelper: return False return True + self.broadcast_with_fn(filter_fn, event_type, data) + + def broadcast_with_fn(self, filter_fn, event_type: str, data): clients = list(filter(filter_fn, self.clients)) logger.debug('Sending to {} out of {} clients: {}'.format(len(clients), len(self.clients), json.dumps({'event': event_type, 'data': data}))) diff --git a/app/frontend/templates/panel/contribute.html b/app/frontend/templates/panel/contribute.html index e7727d2f..5ca38c6b 100644 --- a/app/frontend/templates/panel/contribute.html +++ b/app/frontend/templates/panel/contribute.html @@ -23,7 +23,7 @@
-
+
@@ -31,8 +31,8 @@

- Patrons get access to several perks, such as behind the scenes videos, posts, and updates. - Patrons also get access to a Crafty Controller PE (Patreon Edition) with additional functions not in other versions of Crafty. + Patrons get access to several perks, such as behind the scenes videos, posts, and updates.
+ Patrons also get early access to new software!


@@ -44,35 +44,7 @@
-
-
-
- -

One Time Support

- -
-

- Contribute via Paypal, you can contribute any amount, as often or as little as you want. - Please understand that while PayPal calls this a "Donation"; this is not a charitable donation and can not be claimed - as a charitable donation for tax purposes -

-
-
-
- - - - - -
-
-
- -
-
-
- -
+
@@ -93,6 +65,28 @@
+
+
+
+ +

More Ways Coming Soon...

+ +
+

+ Thank you for your interest in contributing to Aracdia Technology's Crafty Controller. + We are always thinking of new ways for our community to contribute to this awesome project.

If you don't see + a contribution method that peaks your interest now please check back soon. +

+
+
+ +
+
+ +
+
+
+
diff --git a/app/frontend/templates/panel/dashboard.html b/app/frontend/templates/panel/dashboard.html index 17b7bffb..0b584423 100644 --- a/app/frontend/templates/panel/dashboard.html +++ b/app/frontend/templates/panel/dashboard.html @@ -366,7 +366,7 @@ dialog.init(function(){ } if (webSocket) { - webSocket.on('send_start_reload', function (start_error) { + webSocket.on('send_start_reload', function () { location.reload() }); } diff --git a/app/frontend/templates/panel/server_term.html b/app/frontend/templates/panel/server_term.html index 70c8b44a..7ab9e733 100644 --- a/app/frontend/templates/panel/server_term.html +++ b/app/frontend/templates/panel/server_term.html @@ -127,13 +127,17 @@ if (webSocket) { webSocket.on('update_button_status', function (updateButton) { if (updateButton.isUpdating){ + if(updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') { console.log(updateButton.isUpdating) document.getElementById('control_buttons').innerHTML = ''; + } } else{ + if (updateButton.server_id == '{{ data['server_stats']['server_id']['server_id'] }}') { window.location.reload() document.getElementById('update_control_buttons').innerHTML = ''; - } + } + } }); } // Convert running to lower case (example: 'True' converts to 'true') and diff --git a/app/frontend/templates/server/wizard.html b/app/frontend/templates/server/wizard.html index e1dad9c0..051114d3 100644 --- a/app/frontend/templates/server/wizard.html +++ b/app/frontend/templates/server/wizard.html @@ -15,14 +15,14 @@

-

+ {% raw xsrf_form_html() %}
- + {% for s in data['server_types'] %} {% end %} @@ -33,8 +33,8 @@
- +
@@ -42,7 +42,7 @@
- +
@@ -55,21 +55,21 @@
- +
- +
- +
@@ -97,7 +97,7 @@
- + @@ -114,7 +114,7 @@

-

+ {% raw xsrf_form_html() %}
@@ -122,21 +122,21 @@
- +
- +
- +
@@ -151,21 +151,21 @@
- +
- +
- +
@@ -192,7 +192,7 @@
- + @@ -209,7 +209,7 @@

-

+ {% raw xsrf_form_html() %} @@ -218,21 +218,21 @@
- +
- +
- +
@@ -247,21 +247,21 @@
- +
- +
- +
@@ -290,7 +290,7 @@
- +