mirror of
https://github.com/RedDeadDepresso/KKAFIO.git
synced 2025-12-22 17:30:01 +00:00
feat: thread manager
This commit is contained in:
@@ -19,12 +19,23 @@ class Logger:
|
|||||||
# logger box signal is used to output log to logger box
|
# logger box signal is used to output log to logger box
|
||||||
self.logs = ""
|
self.logs = ""
|
||||||
self.logger_signal = signalBus.loggerSignal
|
self.logger_signal = signalBus.loggerSignal
|
||||||
self.logger = logging.getLogger("BAAS_Logger")
|
self.logger = logging.getLogger("KAFFIO_Logger")
|
||||||
formatter = logging.Formatter("%(levelname)8s |%(asctime)20s | %(message)s ")
|
formatter = logging.Formatter("%(levelname)8s |%(category)s | %(message)s ")
|
||||||
handler1 = logging.StreamHandler(stream=sys.stdout)
|
handler1 = logging.StreamHandler(stream=sys.stdout)
|
||||||
handler1.setFormatter(formatter)
|
handler1.setFormatter(formatter)
|
||||||
self.logger.setLevel(logging.INFO)
|
self.logger.setLevel(logging.INFO)
|
||||||
self.logger.addHandler(handler1)
|
self.logger.addHandler(handler1)
|
||||||
|
self.text = ['INFO', 'SUCCESS', 'ERROR', 'SKIPPED', 'REPLACED', 'RENAMED', 'REMOVED']
|
||||||
|
# Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
|
||||||
|
self.status = [' INFO', ' SUCCESS', ' ERROR',
|
||||||
|
' SKIPPED', ' REPLACED', ' RENAMED', ' REMOVED']
|
||||||
|
# Status Color: Blue, Red, Green, Orange,
|
||||||
|
self.statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
|
||||||
|
|
||||||
|
# Status HTML: <b style="color:$color">status</b>
|
||||||
|
self.statusHtml = [
|
||||||
|
f'<b style="color:{_color};">{status}</b>'
|
||||||
|
for _color, status in zip(self.statusColor, self.status)]
|
||||||
|
|
||||||
def __out__(self, category: str, message: str, level: int = 1, raw_print=False) -> None:
|
def __out__(self, category: str, message: str, level: int = 1, raw_print=False) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -41,30 +52,34 @@ class Logger:
|
|||||||
|
|
||||||
while len(logging.root.handlers) > 0:
|
while len(logging.root.handlers) > 0:
|
||||||
logging.root.handlers.pop()
|
logging.root.handlers.pop()
|
||||||
# Status Text: INFO, SUCCESS, ERROR, SKIPPED, REPLACED, RENAMED, REMOVED
|
|
||||||
status = [' INFO', ' SUCCESS', ' ERROR',
|
|
||||||
' SKIPPED', ' REPLACED', ' RENAMED', ' REMOVED']
|
|
||||||
|
|
||||||
# Status Color: Blue, Red, Green, Orange,
|
|
||||||
statusColor = ['#2d8cf0', '#ed3f14', '#f90', '#f90', '#f90', '#f90', '#00c12b']
|
|
||||||
|
|
||||||
# Status HTML: <b style="color:$color">status</b>
|
|
||||||
statusHtml = [
|
|
||||||
f'<b style="color:{_color};">{status}</b>'
|
|
||||||
for _color, status in zip(statusColor, status)]
|
|
||||||
# If logger box is not None, output log to logger box
|
# If logger box is not None, output log to logger box
|
||||||
# else output log to console
|
# else output log to console
|
||||||
if self.logger_signal is not None:
|
if self.logger_signal is not None:
|
||||||
message = message.replace('\n', '<br>').replace(' ', ' ')
|
message = message.replace('\n', '<br>').replace(' ', ' ')
|
||||||
adding = (f'''
|
adding = (f'''
|
||||||
<div style="font-family: Consolas, monospace;color:{statusColor[level - 1]};">
|
<div style="font-family: Consolas, monospace;color:{self.statusColor[level - 1]};">
|
||||||
{statusHtml[level - 1]} | {category} | {message}
|
{self.statusHtml[level - 1]} | {category} | {message}
|
||||||
</div>
|
</div>
|
||||||
''')
|
''')
|
||||||
self.logs += adding
|
self.logs += adding
|
||||||
self.logger_signal.emit(adding)
|
self.logger_signal.emit(adding)
|
||||||
else:
|
else:
|
||||||
print(f'{statusHtml[level - 1]} | {datetime.now().strftime("%Y-%m-%d %H:%M:%S")} | {message}')
|
print(f'{self.statusHtml[level - 1]} | {category} | {message}')
|
||||||
|
|
||||||
|
def colorize(self, line):
|
||||||
|
adding = line
|
||||||
|
for i, s in enumerate(self.text):
|
||||||
|
if s in line:
|
||||||
|
adding = (f'''
|
||||||
|
<div style="font-family: Consolas, monospace;color:{self.statusColor[i]};">
|
||||||
|
{line}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
''')
|
||||||
|
break
|
||||||
|
self.logs += adding
|
||||||
|
self.logger_signal.emit(adding)
|
||||||
|
|
||||||
def info(self, category: str, message: str) -> None:
|
def info(self, category: str, message: str) -> None:
|
||||||
"""
|
"""
|
||||||
@@ -120,7 +135,7 @@ class Logger:
|
|||||||
|
|
||||||
Output warn log
|
Output warn log
|
||||||
"""
|
"""
|
||||||
self.__out__(category, message, 6)
|
self.__out__(category, message, 7)
|
||||||
|
|
||||||
def line(self) -> None:
|
def line(self) -> None:
|
||||||
"""
|
"""
|
||||||
|
|||||||
41
app/common/thread_manager.py
Normal file
41
app/common/thread_manager.py
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
import threading
|
||||||
|
|
||||||
|
from app.common.signal_bus import signalBus
|
||||||
|
from app.common.logger import logger
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadManager:
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self._script = None
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
if self._script is not None:
|
||||||
|
self.stop()
|
||||||
|
else:
|
||||||
|
args = []
|
||||||
|
if os.path.exists("script.exe"):
|
||||||
|
args = ["script.exe"]
|
||||||
|
elif os.path.exists("script.py"):
|
||||||
|
args = ["python", "script.py"]
|
||||||
|
self._script = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
threading.Thread(target=self.readOutput).start()
|
||||||
|
|
||||||
|
def readOutput(self):
|
||||||
|
while self._script is not None:
|
||||||
|
line = self._script.stdout.readline().decode('utf-8')
|
||||||
|
if not line:
|
||||||
|
signalBus.stopSignal.emit()
|
||||||
|
else:
|
||||||
|
logger.colorize(line)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self._script.terminate()
|
||||||
|
self._script = None
|
||||||
|
|
||||||
|
|
||||||
|
threadManager = ThreadManager()
|
||||||
|
signalBus.startSignal.connect(threadManager.start)
|
||||||
|
signalBus.stopSignal.connect(threadManager.stop)
|
||||||
@@ -37,6 +37,7 @@ class NavigationActionButtons(QWidget):
|
|||||||
def __connectSignalToSlot(self):
|
def __connectSignalToSlot(self):
|
||||||
self.selectAllButton.clicked.connect(self.onSelectAllClicked)
|
self.selectAllButton.clicked.connect(self.onSelectAllClicked)
|
||||||
self.clearAllButton.clicked.connect(self.onClearAllClicked)
|
self.clearAllButton.clicked.connect(self.onClearAllClicked)
|
||||||
|
self.startButton.clicked.connect(self.onStartClicked)
|
||||||
|
|
||||||
signalBus.startSignal.connect(lambda: self.startButton.setText("Stop"))
|
signalBus.startSignal.connect(lambda: self.startButton.setText("Stop"))
|
||||||
signalBus.stopSignal.connect(lambda: self.startButton.setText("Start"))
|
signalBus.stopSignal.connect(lambda: self.startButton.setText("Start"))
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ class Handler:
|
|||||||
|
|
||||||
def loadConfig(self, config):
|
def loadConfig(self, config):
|
||||||
self.gamePath = config.get("Core", "GamePath")
|
self.gamePath = config.get("Core", "GamePath")
|
||||||
self.config = config.get(str(self))
|
key = str(self).replace(" ", "")
|
||||||
|
self.config = config.get(key)
|
||||||
|
|
||||||
def handle(self, request):
|
def handle(self, request):
|
||||||
pass
|
pass
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ class Request:
|
|||||||
logger.info("SCRIPT", "Validating config")
|
logger.info("SCRIPT", "Validating config")
|
||||||
self.validateGamepath()
|
self.validateGamepath()
|
||||||
self._handlers = [x for x in self.handlers if self.isTaskEnabled(x)]
|
self._handlers = [x for x in self.handlers if self.isTaskEnabled(x)]
|
||||||
|
|
||||||
|
if not self._handlers:
|
||||||
|
logger.error("SCRIPT", "No task enabled")
|
||||||
if not self._isValid:
|
if not self._isValid:
|
||||||
raise Exception()
|
raise Exception()
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ class LoggerInterface(QFrame):
|
|||||||
self.autoscrollButton = PushButton('Autoscroll Off')
|
self.autoscrollButton = PushButton('Autoscroll Off')
|
||||||
self.loggerBox = TextEdit()
|
self.loggerBox = TextEdit()
|
||||||
self.loggerBox.setReadOnly(True)
|
self.loggerBox.setReadOnly(True)
|
||||||
|
signalBus.guiMode = True
|
||||||
|
|
||||||
self.__initWidget()
|
self.__initWidget()
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ from .logger_interface import LoggerInterface
|
|||||||
from .setting_interface import SettingInterface
|
from .setting_interface import SettingInterface
|
||||||
from ..common.config import ZH_SUPPORT_URL, EN_SUPPORT_URL, cfg
|
from ..common.config import ZH_SUPPORT_URL, EN_SUPPORT_URL, cfg
|
||||||
from ..common.signal_bus import signalBus
|
from ..common.signal_bus import signalBus
|
||||||
|
from ..common.thread_manager import threadManager
|
||||||
from ..common import resource
|
from ..common import resource
|
||||||
from ..components.navigation_checkbox import NavigationCheckBox
|
from ..components.navigation_checkbox import NavigationCheckBox
|
||||||
from ..components.navigation_action_buttons import NavigationActionButtons
|
from ..components.navigation_action_buttons import NavigationActionButtons
|
||||||
|
|||||||
67
script.py
67
script.py
@@ -1,66 +1,5 @@
|
|||||||
import sys
|
from app.modules.request import Request
|
||||||
import traceback
|
|
||||||
try:
|
|
||||||
with open('traceback.log', 'w') as f:
|
|
||||||
pass
|
|
||||||
|
|
||||||
from app.common.logger import logger
|
|
||||||
from app.modules.install_chara import InstallChara
|
|
||||||
from app.modules.remove_chara import RemoveChara
|
|
||||||
from app.modules.fc_kks import FilterConvertKKS
|
|
||||||
from app.modules.create_backup import CreateBackup
|
|
||||||
|
|
||||||
|
|
||||||
class Script:
|
request = Request()
|
||||||
def __init__(self, config, file_manager):
|
request.process()
|
||||||
"""Initializes the primary azurlane-auto instance with the passed in
|
|
||||||
Config instance;
|
|
||||||
|
|
||||||
Args:
|
|
||||||
config (Config): BAAuto Config instance
|
|
||||||
"""
|
|
||||||
self.config = config
|
|
||||||
fileManager = file_manager
|
|
||||||
self.modules = {
|
|
||||||
'InstallChara': None,
|
|
||||||
'RemoveChara': None,
|
|
||||||
'CreateBackup': None,
|
|
||||||
'FCKKS': None,
|
|
||||||
}
|
|
||||||
if self.config.install_chara['Enable']:
|
|
||||||
self.modules['InstallChara'] = InstallChara(self.config, fileManager)
|
|
||||||
if self.config.remove_chara['Enable']:
|
|
||||||
self.modules['RemoveChara'] = RemoveChara(self.config, fileManager)
|
|
||||||
if self.config.create_backup['Enable']:
|
|
||||||
self.modules['CreateBackup'] = CreateBackup(self.config, fileManager)
|
|
||||||
if self.config.fc_kks["Enable"]:
|
|
||||||
self.modules['FCKKS'] = FilterConvertKKS(self.config, fileManager)
|
|
||||||
|
|
||||||
def run(self):
|
|
||||||
for task in self.config.tasks:
|
|
||||||
if self.modules[task]:
|
|
||||||
logger.info("SCRIPT", f'Start Task: {task}')
|
|
||||||
try:
|
|
||||||
self.modules[task].logic_wrapper()
|
|
||||||
except:
|
|
||||||
logger.error("SCRIPT", f'Task error: {task}. For more info, check the traceback.log file.')
|
|
||||||
with open('traceback.log', 'a') as f:
|
|
||||||
f.write(f'[{task}]\n')
|
|
||||||
traceback.print_exc(None, f, True)
|
|
||||||
f.write('\n')
|
|
||||||
sys.exit(1)
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
except:
|
|
||||||
print(f'[ERROR] Script Initialisation Error. For more info, check the traceback.log file.')
|
|
||||||
with open('traceback.log', 'w') as f:
|
|
||||||
f.write(f'Script Initialisation Error\n')
|
|
||||||
traceback.print_exc(None, f, True)
|
|
||||||
f.write('\n')
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
config = Config('config.json')
|
|
||||||
file_manager = FileManager(config)
|
|
||||||
script = Script(config, file_manager)
|
|
||||||
script.run()
|
|
||||||
Reference in New Issue
Block a user