Added batch script execution function
This commit is contained in:
parent
3090a0f68d
commit
ed496a08c2
277
Galactic.py
277
Galactic.py
|
@ -40,7 +40,7 @@ from selenium.common.exceptions import NoSuchWindowException
|
||||||
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings, QWebEngineProfile
|
from PyQt5.QtWebEngineWidgets import QWebEngineView, QWebEngineSettings, QWebEngineProfile
|
||||||
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
|
from PyQt5.QtWebEngineCore import QWebEngineUrlRequestInterceptor
|
||||||
from PyQt5.QtNetwork import QNetworkProxyFactory
|
from PyQt5.QtNetwork import QNetworkProxyFactory
|
||||||
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QSystemTrayIcon, QMenu, QAction, QDesktopWidget, QShortcut
|
from PyQt5.QtWidgets import QApplication, QMainWindow, QMessageBox, QSystemTrayIcon, QMenu, QAction, QDesktopWidget, QShortcut, QFileDialog
|
||||||
from PyQt5.QtCore import Qt, QCoreApplication, QTimer, QUrl
|
from PyQt5.QtCore import Qt, QCoreApplication, QTimer, QUrl
|
||||||
from PyQt5.QtGui import QIcon, QKeySequence
|
from PyQt5.QtGui import QIcon, QKeySequence
|
||||||
from typing import List
|
from typing import List
|
||||||
|
@ -1206,22 +1206,38 @@ class BrowserPluginParent:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.app_id = None
|
self.app_id = None
|
||||||
self.thread = None
|
self.thread = None
|
||||||
|
self.result_color = None
|
||||||
self.result = None
|
self.result = None
|
||||||
self.run_task_exception = None
|
self.exception = None
|
||||||
self.user_id = None
|
self.user_id = None
|
||||||
self.instant_message = None
|
self.instant_message = None
|
||||||
|
self.batch_mode = None
|
||||||
|
self._rs = 0
|
||||||
|
self._re = 0
|
||||||
|
|
||||||
|
@property
|
||||||
|
def running_time(self):
|
||||||
|
return (int(time.time()) - self._rs) if self._rs > self._re else (self._re - self._rs)
|
||||||
|
|
||||||
def _run_task(self, *args, **kwargs):
|
def _run_task(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
self.result = self.running(*args, **kwargs) or ''
|
self._rs = int(time.time())
|
||||||
|
res = self.running(*args, **kwargs)
|
||||||
|
if isinstance(res, (tuple, list)):
|
||||||
|
self.result_color = res[0]
|
||||||
|
self.result = res[1]
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.run_task_exception = e
|
self.exception = e
|
||||||
self.message_except(e)
|
self.message_except(e)
|
||||||
|
finally:
|
||||||
|
self._re = int(time.time())
|
||||||
|
|
||||||
def message(self, message=None):
|
def message(self, message=None):
|
||||||
print('[%s]: %s' % (str(self.app_id), message), file=sys.stderr)
|
print('[%s]: %s' % (str(self.app_id), message), file=sys.stderr)
|
||||||
if len(str(message)) <= 4096:
|
if len(str(message)) <= 4096:
|
||||||
notification_send(app_id=self.app_id, title=self.name, message='%s' % (message,))
|
notification_send(app_id=self.app_id, title=self.name, message='%s' % (message,))
|
||||||
|
if (self.batch_mode is True) == 1:
|
||||||
|
return None
|
||||||
self.instant_message and self.instant_message(json.dumps({
|
self.instant_message and self.instant_message(json.dumps({
|
||||||
'time': int(time.time()), 'type': 'message', 'data': {'user_id': str(self.user_id), 'content': str(message), 'title': str(self.app_id)}
|
'time': int(time.time()), 'type': 'message', 'data': {'user_id': str(self.user_id), 'content': str(message), 'title': str(self.app_id)}
|
||||||
}))
|
}))
|
||||||
|
@ -1241,7 +1257,7 @@ class BrowserPluginParent:
|
||||||
params = BrowserPluginRunningParam({'driver': driver, 'message': self.message, 'logging': self.logging, 'requirements': requirements})
|
params = BrowserPluginRunningParam({'driver': driver, 'message': self.message, 'logging': self.logging, 'requirements': requirements})
|
||||||
thread = threading.Thread(target=self._run_task, args=(params,))
|
thread = threading.Thread(target=self._run_task, args=(params,))
|
||||||
self.thread = thread
|
self.thread = thread
|
||||||
thread.daemon = False
|
thread.daemon = True
|
||||||
thread.start()
|
thread.start()
|
||||||
return thread
|
return thread
|
||||||
|
|
||||||
|
@ -1254,7 +1270,7 @@ class BrowserPluginParent:
|
||||||
self.thread = None
|
self.thread = None
|
||||||
|
|
||||||
def state(self):
|
def state(self):
|
||||||
return self.thread.is_alive() if self.thread else None
|
return self.thread.is_alive() if self.thread else False
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param: BrowserPluginRunningParam):
|
def running(param: BrowserPluginRunningParam):
|
||||||
|
@ -1273,6 +1289,7 @@ class BrowserPluginFileTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.message(param.requirements)
|
param.message(param.requirements)
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginMultFileTest(BrowserPluginParent):
|
class BrowserPluginMultFileTest(BrowserPluginParent):
|
||||||
|
@ -1287,6 +1304,7 @@ class BrowserPluginMultFileTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.message(param.requirements)
|
param.message(param.requirements)
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginTextTest(BrowserPluginParent):
|
class BrowserPluginTextTest(BrowserPluginParent):
|
||||||
|
@ -1301,6 +1319,7 @@ class BrowserPluginTextTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.message(param.requirements)
|
param.message(param.requirements)
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginMultTextTest(BrowserPluginParent):
|
class BrowserPluginMultTextTest(BrowserPluginParent):
|
||||||
|
@ -1315,6 +1334,7 @@ class BrowserPluginMultTextTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.message(param.requirements)
|
param.message(param.requirements)
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginLoggingTest(BrowserPluginParent):
|
class BrowserPluginLoggingTest(BrowserPluginParent):
|
||||||
|
@ -1329,6 +1349,7 @@ class BrowserPluginLoggingTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.logging(param.requirements[0])
|
param.logging(param.requirements[0])
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginMessageTest(BrowserPluginParent):
|
class BrowserPluginMessageTest(BrowserPluginParent):
|
||||||
|
@ -1343,6 +1364,7 @@ class BrowserPluginMessageTest(BrowserPluginParent):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def running(param):
|
def running(param):
|
||||||
param.message(param.requirements[0])
|
param.message(param.requirements[0])
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginFileCommandDebug(BrowserPluginParent):
|
class BrowserPluginFileCommandDebug(BrowserPluginParent):
|
||||||
|
@ -1358,6 +1380,7 @@ class BrowserPluginFileCommandDebug(BrowserPluginParent):
|
||||||
def running(param):
|
def running(param):
|
||||||
file = param.requirements[0][0]['path']
|
file = param.requirements[0][0]['path']
|
||||||
exec(open(file, mode='r', encoding='utf-8').read())
|
exec(open(file, mode='r', encoding='utf-8').read())
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserPluginTextCommandDebug(BrowserPluginParent):
|
class BrowserPluginTextCommandDebug(BrowserPluginParent):
|
||||||
|
@ -1373,6 +1396,7 @@ class BrowserPluginTextCommandDebug(BrowserPluginParent):
|
||||||
def running(param):
|
def running(param):
|
||||||
code = param.requirements[0]
|
code = param.requirements[0]
|
||||||
code and exec(code)
|
code and exec(code)
|
||||||
|
return '#FFFFFF', '已完成'
|
||||||
|
|
||||||
|
|
||||||
class BrowserManagerDataStorage(dict):
|
class BrowserManagerDataStorage(dict):
|
||||||
|
@ -1455,14 +1479,6 @@ class BrowserManagerUserRunning:
|
||||||
return False
|
return False
|
||||||
except PermissionError:
|
except PermissionError:
|
||||||
return True
|
return True
|
||||||
# s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
|
||||||
# s.settimeout(0.01)
|
|
||||||
# try:
|
|
||||||
# return s.connect_ex(('127.0.0.1', self.remote_debugging_port)) == 0
|
|
||||||
# except socket.timeout:
|
|
||||||
# return False
|
|
||||||
# finally:
|
|
||||||
# s.close()
|
|
||||||
|
|
||||||
@func_set_timeout(0.05)
|
@func_set_timeout(0.05)
|
||||||
def _get_window_handles(self):
|
def _get_window_handles(self):
|
||||||
|
@ -1533,11 +1549,14 @@ class BrowserManagerUserRunning:
|
||||||
'user_data_dir': self.user_data_dir,
|
'user_data_dir': self.user_data_dir,
|
||||||
'remote_debugging_port': self.remote_debugging_port,
|
'remote_debugging_port': self.remote_debugging_port,
|
||||||
'is_running': self.is_running,
|
'is_running': self.is_running,
|
||||||
'current_plugin_executing': self.plugin.id if self.plugin and self.plugin.state() else None,
|
|
||||||
'url': self.url,
|
'url': self.url,
|
||||||
'title': self.title,
|
'title': self.title,
|
||||||
'alert': self.alert,
|
'alert': self.alert,
|
||||||
'window_handles': self.window_handles
|
'window_handles': self.window_handles,
|
||||||
|
'plugin_running': self.plugin.state() if self.plugin else False,
|
||||||
|
'plugin_running_time': self.plugin.running_time if self.plugin else None,
|
||||||
|
'plugin_execution_result': self.plugin.result if self.plugin else None,
|
||||||
|
'plugin_execution_result_color': self.plugin.result_color if self.plugin else None
|
||||||
}
|
}
|
||||||
|
|
||||||
def app_id(self):
|
def app_id(self):
|
||||||
|
@ -1553,6 +1572,46 @@ class BrowserManagerUserRunning:
|
||||||
self.user_name = user_name
|
self.user_name = user_name
|
||||||
|
|
||||||
|
|
||||||
|
class BrowserManagerBusy(Exception):
|
||||||
|
def __init__(self, message):
|
||||||
|
self.message = message
|
||||||
|
super().__init__(self.message)
|
||||||
|
|
||||||
|
|
||||||
|
class BrowserPluginBatchExecution:
|
||||||
|
def __init__(self):
|
||||||
|
self.plugin_id = None
|
||||||
|
self.plugin_name = None
|
||||||
|
self.plugin_time = None
|
||||||
|
self.users = None
|
||||||
|
self.plugins = None
|
||||||
|
self.results = None
|
||||||
|
self.running = None
|
||||||
|
|
||||||
|
def set_plugin_for_monitor(self, users: list, plugins: list, plugin_id: str, plugin_name: str):
|
||||||
|
if self.running is True:
|
||||||
|
raise Exception('Running.')
|
||||||
|
self.plugin_id = plugin_id
|
||||||
|
self.plugin_name = plugin_name
|
||||||
|
self.plugin_time = int(time.time())
|
||||||
|
self.users = users
|
||||||
|
self.plugins = plugins
|
||||||
|
threading.Thread(target=self._monitor_until_all_completed).start()
|
||||||
|
|
||||||
|
def _monitor_until_all_completed(self):
|
||||||
|
if not isinstance(self.plugins, list):
|
||||||
|
return None
|
||||||
|
self.results = []
|
||||||
|
self.running = True
|
||||||
|
while True:
|
||||||
|
time.sleep(2.5)
|
||||||
|
if all(not plugin.state() for plugin in self.plugins):
|
||||||
|
break
|
||||||
|
for plugin in self.plugins:
|
||||||
|
self.results.append([plugin.app_id, plugin.running_time, plugin.result])
|
||||||
|
self.running = False
|
||||||
|
|
||||||
|
|
||||||
class BrowserManager:
|
class BrowserManager:
|
||||||
def __init__(self, runner, driver: str, binary: str, plugin_result_dir: str, manager_data_file: str, browser_data_home: str, browser_init_home: str, use_selenium_wire: int):
|
def __init__(self, runner, driver: str, binary: str, plugin_result_dir: str, manager_data_file: str, browser_data_home: str, browser_init_home: str, use_selenium_wire: int):
|
||||||
self.runner = runner
|
self.runner = runner
|
||||||
|
@ -1580,6 +1639,7 @@ class BrowserManager:
|
||||||
self.user_in_operation = []
|
self.user_in_operation = []
|
||||||
self.plugins_int = {}
|
self.plugins_int = {}
|
||||||
self.plugins_ext = {}
|
self.plugins_ext = {}
|
||||||
|
self.plugin_batch_execution = BrowserPluginBatchExecution()
|
||||||
|
|
||||||
def _generate_remote_debugging_port(self):
|
def _generate_remote_debugging_port(self):
|
||||||
exist_ports = [value['remote_debugging_port'] for key, value in self.data_storage['browser_user'].items()]
|
exist_ports = [value['remote_debugging_port'] for key, value in self.data_storage['browser_user'].items()]
|
||||||
|
@ -1589,8 +1649,7 @@ class BrowserManager:
|
||||||
for user_id, running in self.user_running.items():
|
for user_id, running in self.user_running.items():
|
||||||
if (not running) == 1:
|
if (not running) == 1:
|
||||||
continue
|
continue
|
||||||
run = BrowserManagerUserRunning(running)
|
running.update_status_running()
|
||||||
run.update_status_running()
|
|
||||||
|
|
||||||
def _get_user_name(self, user_id: str):
|
def _get_user_name(self, user_id: str):
|
||||||
return str(self.data_storage['browser_user'][user_id]['user_name'] or '')
|
return str(self.data_storage['browser_user'][user_id]['user_name'] or '')
|
||||||
|
@ -1731,19 +1790,13 @@ class BrowserManager:
|
||||||
|
|
||||||
def user_operate_starting(self, user_id: str):
|
def user_operate_starting(self, user_id: str):
|
||||||
user_id = str(user_id)
|
user_id = str(user_id)
|
||||||
# with self.threading_lock:
|
|
||||||
# if (user_id not in self.user_in_operation) == 1:
|
|
||||||
# self.user_in_operation.append(user_id)
|
|
||||||
# else:
|
|
||||||
# raise RuntimeError('Busy.')
|
|
||||||
if (user_id not in self.user_in_operation) == 1:
|
if (user_id not in self.user_in_operation) == 1:
|
||||||
self.user_in_operation.append(user_id)
|
self.user_in_operation.append(user_id)
|
||||||
else:
|
else:
|
||||||
raise RuntimeError('Busy.')
|
raise BrowserManagerBusy('Busy.')
|
||||||
|
|
||||||
def user_operate_complete(self, user_id: str):
|
def user_operate_complete(self, user_id: str):
|
||||||
user_id = str(user_id)
|
user_id = str(user_id)
|
||||||
with self.threading_lock:
|
|
||||||
while user_id in self.user_in_operation:
|
while user_id in self.user_in_operation:
|
||||||
self.user_in_operation.remove(user_id)
|
self.user_in_operation.remove(user_id)
|
||||||
|
|
||||||
|
@ -1783,8 +1836,12 @@ class BrowserManager:
|
||||||
plugin = self.plugins[plugin_id]()
|
plugin = self.plugins[plugin_id]()
|
||||||
plugin.run(self._get_user_app_id(user_id), user_id, driver, requirements, self.runner.web_server.websocket_connection_manager.send_broadcast_use_sync)
|
plugin.run(self._get_user_app_id(user_id), user_id, driver, requirements, self.runner.web_server.websocket_connection_manager.send_broadcast_use_sync)
|
||||||
running.set_plugin(plugin)
|
running.set_plugin(plugin)
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def plugin_shutdown(self, user_id: str):
|
def plugin_shutdown(self, user_id: str):
|
||||||
|
@ -1797,8 +1854,45 @@ class BrowserManager:
|
||||||
raise Exception('The plugin is not running.')
|
raise Exception('The plugin is not running.')
|
||||||
plugin = running.plugin
|
plugin = running.plugin
|
||||||
plugin.interrupt()
|
plugin.interrupt()
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
|
def plugin_all_users_run(self, plugin_id: str, requirements=None):
|
||||||
|
try:
|
||||||
|
if (self.plugin_batch_execution.running is True) == 1:
|
||||||
|
raise Exception('Still in batch execution.')
|
||||||
|
users = []
|
||||||
|
plugins = []
|
||||||
|
for user_id in self.user_ids_online():
|
||||||
|
try:
|
||||||
|
self.plugin_run(user_id, plugin_id, requirements)
|
||||||
|
users.append(user_id)
|
||||||
|
plugin = BrowserManagerUserRunning(self.user_running[user_id]).plugin
|
||||||
|
plugin.batch_mode = True
|
||||||
|
plugins.append(plugin)
|
||||||
|
time.sleep(0.1)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.plugin_batch_execution.set_plugin_for_monitor(users, plugins, plugin_id, self.plugins[plugin_id].name)
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
|
||||||
|
def plugin_all_users_shutdown(self):
|
||||||
|
try:
|
||||||
|
for user_id in self.plugin_batch_execution.users:
|
||||||
|
try:
|
||||||
|
self.plugin_shutdown(user_id)
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def plugin_list(self):
|
||||||
|
return {plugin_id: {'name': plugin_class.name, 'requirements': plugin_class.requirements} for plugin_id, plugin_class in self.plugins.items()}
|
||||||
|
|
||||||
def user_ids(self):
|
def user_ids(self):
|
||||||
return [user_id for user_id in self.data_storage['browser_user'].keys()]
|
return [user_id for user_id in self.data_storage['browser_user'].keys()]
|
||||||
|
@ -1808,14 +1902,17 @@ class BrowserManager:
|
||||||
return [user_id for user_id, running in self.user_running.items() if running and running.is_running]
|
return [user_id for user_id, running in self.user_running.items() if running and running.is_running]
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def user_all_details(self, user_id: str = None):
|
def user_all_details(self):
|
||||||
plugins = {plugin_id: {'name': plugin_class.name, 'requirements': plugin_class.requirements} for plugin_id, plugin_class in self.plugins.items()}
|
|
||||||
details = {user_id: self.user_running[user_id].status() for user_id in self.user_ids() if user_id in self.user_running.keys()}
|
details = {user_id: self.user_running[user_id].status() for user_id in self.user_ids() if user_id in self.user_running.keys()}
|
||||||
details = {user_id: {**detail, **{'plugins': plugins}} for user_id, detail in details.items()}
|
return {
|
||||||
if (user_id and user_id in details.keys()) == 1:
|
'user_online_count': len(self.user_ids_online()),
|
||||||
return details[user_id]
|
'user_details': details,
|
||||||
else:
|
'plugin_batch_execution_id': self.plugin_batch_execution.plugin_id,
|
||||||
return details
|
'plugin_batch_execution_name': self.plugin_batch_execution.plugin_name,
|
||||||
|
'plugin_batch_execution_time': self.plugin_batch_execution.plugin_time,
|
||||||
|
'plugin_batch_execution_status': self.plugin_batch_execution.running,
|
||||||
|
'plugin_batch_execution_result': self.plugin_batch_execution.results
|
||||||
|
}
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def user_set_name(self, user_id: str, user_name: str):
|
def user_set_name(self, user_id: str, user_name: str):
|
||||||
|
@ -1829,8 +1926,12 @@ class BrowserManager:
|
||||||
self.data_storage['browser_user'][user_id]['user_name'] = user_name
|
self.data_storage['browser_user'][user_id]['user_name'] = user_name
|
||||||
self.data_storage.save()
|
self.data_storage.save()
|
||||||
self.user_running[user_id].set_user_name(user_name)
|
self.user_running[user_id].set_user_name(user_name)
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
@func_set_timeout(0.55)
|
@func_set_timeout(0.55)
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
|
@ -1871,8 +1972,12 @@ class BrowserManager:
|
||||||
os.path.exists(data_dir) or shutil.copytree(self.browser_init_home, data_dir)
|
os.path.exists(data_dir) or shutil.copytree(self.browser_init_home, data_dir)
|
||||||
else:
|
else:
|
||||||
os.path.exists(data_dir) or os.makedirs(data_dir)
|
os.path.exists(data_dir) or os.makedirs(data_dir)
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def user_del(self, user_id: str):
|
def user_del(self, user_id: str):
|
||||||
|
@ -1889,8 +1994,12 @@ class BrowserManager:
|
||||||
self.data_storage['browser_user'].pop(user_id)
|
self.data_storage['browser_user'].pop(user_id)
|
||||||
self.data_storage.save()
|
self.data_storage.save()
|
||||||
self.user_running.pop(user_id)
|
self.user_running.pop(user_id)
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def user_run(self, user_id: str):
|
def user_run(self, user_id: str):
|
||||||
|
@ -1917,8 +2026,12 @@ class BrowserManager:
|
||||||
res_interceptor=self.use_selenium_wire and self.res_interceptor
|
res_interceptor=self.use_selenium_wire and self.res_interceptor
|
||||||
)
|
)
|
||||||
running.set_driver(driver)
|
running.set_driver(driver)
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
@calculate_execution_time
|
@calculate_execution_time
|
||||||
def user_die(self, user_id: str):
|
def user_die(self, user_id: str):
|
||||||
|
@ -1944,8 +2057,45 @@ class BrowserManager:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
raise Exception('The debug port is not in listening.')
|
raise Exception('The debug port is not in listening.')
|
||||||
finally:
|
|
||||||
self.user_operate_complete(user_id)
|
self.user_operate_complete(user_id)
|
||||||
|
except BrowserManagerBusy:
|
||||||
|
raise
|
||||||
|
except Exception:
|
||||||
|
self.user_operate_complete(user_id)
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
|
class ApplicationSetting(dict):
|
||||||
|
def __init__(self, file: str):
|
||||||
|
self._data_file = os.path.abspath(file)
|
||||||
|
super().__init__(self._get_json_data(self._data_file, {}))
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _get_json_data(file: str, data=None):
|
||||||
|
if os.path.exists(file):
|
||||||
|
try:
|
||||||
|
return json.loads(open(file=file, mode='r', encoding='utf-8').read())
|
||||||
|
except json.decoder.JSONDecodeError:
|
||||||
|
return data
|
||||||
|
return data
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _put_json_data(file: str, data=None):
|
||||||
|
with open(file=file, mode='w', encoding='utf-8') as f:
|
||||||
|
flock(f, LOCK_EX)
|
||||||
|
res = f.write(json.dumps(data, indent=4, ensure_ascii=True))
|
||||||
|
flock(f, LOCK_UN)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def __getitem__(self, item):
|
||||||
|
if item in self:
|
||||||
|
return super().__getitem__(item)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def __setitem__(self, key, value):
|
||||||
|
super().__setitem__(key, value)
|
||||||
|
self._put_json_data(self._data_file, self)
|
||||||
|
|
||||||
|
|
||||||
class MainWindow(QMainWindow):
|
class MainWindow(QMainWindow):
|
||||||
|
@ -1968,10 +2118,11 @@ class MainWindow(QMainWindow):
|
||||||
self.setWindowFlags(self.windowFlags() | Qt.WindowMinMaxButtonsHint)
|
self.setWindowFlags(self.windowFlags() | Qt.WindowMinMaxButtonsHint)
|
||||||
screen = QDesktopWidget().screenGeometry()
|
screen = QDesktopWidget().screenGeometry()
|
||||||
self.screen_w, self.screen_h = screen.width(), screen.height()
|
self.screen_w, self.screen_h = screen.width(), screen.height()
|
||||||
self.window_w, self.window_h = round(480 * self.scale_rate), round(868 * self.scale_rate)
|
self.window_w, self.window_h = round(455 * self.scale_rate), round(855 * self.scale_rate)
|
||||||
self.window_x, self.window_y = 0, 0
|
self.window_x, self.window_y = 0, 0
|
||||||
self.setFixedSize(self.window_w, self.window_h)
|
self.setFixedSize(self.window_w, self.window_h)
|
||||||
QNetworkProxyFactory.setUseSystemConfiguration(False)
|
QNetworkProxyFactory.setUseSystemConfiguration(False)
|
||||||
|
self.setting = ApplicationSetting(os.path.join(runner.app_data, 'application.json'))
|
||||||
self.webview = WebEngineView()
|
self.webview = WebEngineView()
|
||||||
self.webview_cache_dir = os.path.join(tempfile.gettempdir(), hashlib.md5(bytes('%s_cache' % (__file__,), encoding='utf-8')).hexdigest()[:32])
|
self.webview_cache_dir = os.path.join(tempfile.gettempdir(), hashlib.md5(bytes('%s_cache' % (__file__,), encoding='utf-8')).hexdigest()[:32])
|
||||||
web_settings = self.webview.settings()
|
web_settings = self.webview.settings()
|
||||||
|
@ -1996,8 +2147,8 @@ class MainWindow(QMainWindow):
|
||||||
['调试:打印环境变量信息', self.on_debug_print_environment],
|
['调试:打印环境变量信息', self.on_debug_print_environment],
|
||||||
['调试:打印模块搜索路径', self.on_debug_print_module_path],
|
['调试:打印模块搜索路径', self.on_debug_print_module_path],
|
||||||
['调试:重新加载外部插件', self.on_debug_reload_external_plugins],
|
['调试:重新加载外部插件', self.on_debug_reload_external_plugins],
|
||||||
|
['配置首选文件', self.on_config_preferred_file],
|
||||||
['重载面板', self.webview.reload],
|
['重载面板', self.webview.reload],
|
||||||
['显示窗口', self.window_show],
|
|
||||||
['退出', self.exit]
|
['退出', self.exit]
|
||||||
]
|
]
|
||||||
for action_item in action_list:
|
for action_item in action_list:
|
||||||
|
@ -2028,7 +2179,8 @@ class MainWindow(QMainWindow):
|
||||||
window_x=self.pos().x(),
|
window_x=self.pos().x(),
|
||||||
window_y=self.pos().y()
|
window_y=self.pos().y()
|
||||||
)
|
)
|
||||||
self.webview.load(QUrl('http://%s:%s/' % ('127.0.0.1' if self.web_listen_host == '0.0.0.0' else self.web_listen_host, self.web_listen_port)))
|
self.webview.load(QUrl('http://%s:%s/index.html' % ('127.0.0.1' if self.web_listen_host == '0.0.0.0' else self.web_listen_host, self.web_listen_port)))
|
||||||
|
self.webview.reload()
|
||||||
|
|
||||||
def exit(self):
|
def exit(self):
|
||||||
self.webview.deleteLater()
|
self.webview.deleteLater()
|
||||||
|
@ -2053,6 +2205,14 @@ class MainWindow(QMainWindow):
|
||||||
def window_position_reset(self):
|
def window_position_reset(self):
|
||||||
self.setGeometry(self.window_x, self.window_y + (self.frameGeometry().height() - self.geometry().height()), self.window_w, self.window_h)
|
self.setGeometry(self.window_x, self.window_y + (self.frameGeometry().height() - self.geometry().height()), self.window_w, self.window_h)
|
||||||
|
|
||||||
|
def on_config_preferred_file(self):
|
||||||
|
self.window_show()
|
||||||
|
filename, _ = QFileDialog.getOpenFileName(self, '选择文件', '/', 'All Files (*)')
|
||||||
|
if (filename and os.path.exists(filename)) == 1:
|
||||||
|
filename = os.path.abspath(filename)
|
||||||
|
self.setting['plugin_preferred_file'] = filename
|
||||||
|
QMessageBox.information(self, '提示', 'The preferred file has changed to %s' % (filename,))
|
||||||
|
|
||||||
def on_tray_icon_update(self):
|
def on_tray_icon_update(self):
|
||||||
self.tray_icon.setToolTip('活跃用户:%s/%s' % (len(self.runner.web_server.browser_manager.user_ids_online()), len(self.runner.web_server.browser_manager.user_ids())))
|
self.tray_icon.setToolTip('活跃用户:%s/%s' % (len(self.runner.web_server.browser_manager.user_ids_online()), len(self.runner.web_server.browser_manager.user_ids())))
|
||||||
|
|
||||||
|
@ -2169,6 +2329,14 @@ class WebServer:
|
||||||
pass
|
pass
|
||||||
await self.websocket_connection_manager.connect(websocket, 1)
|
await self.websocket_connection_manager.connect(websocket, 1)
|
||||||
|
|
||||||
|
@self.app.api_route(methods=['GET', 'POST'], path='/plugin_preferred_file')
|
||||||
|
def api_plugin_preferred_file():
|
||||||
|
file = self.runner.window and self.runner.window.setting['plugin_preferred_file']
|
||||||
|
if (file and os.path.exists(file)) == 1:
|
||||||
|
return JSONResponse(status_code=200, content=self.message(0, '', file))
|
||||||
|
else:
|
||||||
|
return JSONResponse(status_code=200, content=self.message(0, '', None))
|
||||||
|
|
||||||
@self.app.api_route(methods=['POST'], path='/plugin_run')
|
@self.app.api_route(methods=['POST'], path='/plugin_run')
|
||||||
def api_plugin_run(data: WebServerAPIJSONData):
|
def api_plugin_run(data: WebServerAPIJSONData):
|
||||||
try:
|
try:
|
||||||
|
@ -2185,6 +2353,26 @@ class WebServer:
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
return self.message(1, '%s' % (e,))
|
return self.message(1, '%s' % (e,))
|
||||||
|
|
||||||
|
@self.app.api_route(methods=['POST'], path='/plugin_all_users_run')
|
||||||
|
def api_plugin_all_users_run(data: WebServerAPIJSONData):
|
||||||
|
try:
|
||||||
|
self.browser_manager.plugin_all_users_run(data.data['plugin_id'], data.data['requirements'])
|
||||||
|
return self.message(0)
|
||||||
|
except Exception as e:
|
||||||
|
return self.message(1, '%s' % (e,))
|
||||||
|
|
||||||
|
@self.app.api_route(methods=['POST'], path='/plugin_all_users_shutdown')
|
||||||
|
def api_plugin_all_users_shutdown():
|
||||||
|
try:
|
||||||
|
self.browser_manager.plugin_all_users_shutdown()
|
||||||
|
return self.message(0)
|
||||||
|
except Exception as e:
|
||||||
|
return self.message(1, '%s' % (e,))
|
||||||
|
|
||||||
|
@self.app.api_route(methods=['GET', 'POST'], path='/plugin_list')
|
||||||
|
def api_plugin_list():
|
||||||
|
return self.browser_manager.plugin_list()
|
||||||
|
|
||||||
@self.app.api_route(methods=['POST'], path='/upload_files')
|
@self.app.api_route(methods=['POST'], path='/upload_files')
|
||||||
def api_upload_files(files: List[UploadFile] = File(...)):
|
def api_upload_files(files: List[UploadFile] = File(...)):
|
||||||
if (len(files) > 25) == 1:
|
if (len(files) > 25) == 1:
|
||||||
|
@ -2197,7 +2385,7 @@ class WebServer:
|
||||||
file_save_path = os.path.join(self.upload_dir, '%s_%s' % (int(time.time() * 1000), file.filename))
|
file_save_path = os.path.join(self.upload_dir, '%s_%s' % (int(time.time() * 1000), file.filename))
|
||||||
with open(file_save_path, 'wb') as f:
|
with open(file_save_path, 'wb') as f:
|
||||||
f.write(file.file.read())
|
f.write(file.file.read())
|
||||||
uploaded_files.append({'filename': file.filename, 'size': file.size, 'type': file.content_type, 'path': file_save_path})
|
uploaded_files.append(file_save_path)
|
||||||
return JSONResponse(status_code=200, content=self.message(0, '', uploaded_files))
|
return JSONResponse(status_code=200, content=self.message(0, '', uploaded_files))
|
||||||
|
|
||||||
@self.app.api_route(methods=['GET', 'POST'], path='/user_all_details')
|
@self.app.api_route(methods=['GET', 'POST'], path='/user_all_details')
|
||||||
|
@ -2265,7 +2453,7 @@ class WebServer:
|
||||||
|
|
||||||
@self.app.api_route(methods=['GET'], path='/')
|
@self.app.api_route(methods=['GET'], path='/')
|
||||||
def index():
|
def index():
|
||||||
return self.statics(os.path.join(self.www, 'index.html'))
|
raise HTTPException(status_code=403)
|
||||||
|
|
||||||
@self.app.api_route(methods=['GET'], path='/200')
|
@self.app.api_route(methods=['GET'], path='/200')
|
||||||
def state():
|
def state():
|
||||||
|
@ -2435,6 +2623,7 @@ class MainRunner:
|
||||||
sys.path.append(os.path.join(os.path.dirname(__file__), 'site-packages.zip'))
|
sys.path.append(os.path.join(os.path.dirname(__file__), 'site-packages.zip'))
|
||||||
sys.path.append(os.path.join(self.app_data, 'Packages'))
|
sys.path.append(os.path.join(self.app_data, 'Packages'))
|
||||||
sys.path.append(os.path.join(self.app_data, 'site-packages.zip'))
|
sys.path.append(os.path.join(self.app_data, 'site-packages.zip'))
|
||||||
|
print('Startup.', file=sys.stderr)
|
||||||
try:
|
try:
|
||||||
self.preprocessing()
|
self.preprocessing()
|
||||||
except Exception:
|
except Exception:
|
||||||
|
|
File diff suppressed because one or more lines are too long
Loading…
Reference in New Issue