From 9be5ac36065ac03126e5c4a3bb59ffa9dbf8fee6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <101191390+HIllya51@users.noreply.github.com> Date: Mon, 26 Aug 2024 15:07:27 +0800 Subject: [PATCH] fix --- .../LunaTranslator/LunaTranslator.py | 22 ++- .../gui/setting_display_text.py | 21 +-- .../gui/setting_textinput_ocr.py | 84 ++++++++++- .../LunaTranslator/metadata/bangumi.py | 34 ++++- .../LunaTranslator/myutils/ocrutil.py | 3 +- .../LunaTranslator/myutils/utils.py | 17 +++ .../LunaTranslator/textsource/texthook.py | 142 +++++++++++++----- plugins/CMakeLists.txt | 2 +- 8 files changed, 261 insertions(+), 64 deletions(-) diff --git a/LunaTranslator/LunaTranslator/LunaTranslator.py b/LunaTranslator/LunaTranslator/LunaTranslator.py index bc443497..e7c87010 100644 --- a/LunaTranslator/LunaTranslator/LunaTranslator.py +++ b/LunaTranslator/LunaTranslator/LunaTranslator.py @@ -46,10 +46,12 @@ import windows import winsharedutils from winsharedutils import collect_running_pids from myutils.post import POSTSOLVE -from myutils.utils import nowisdark, getfilemd5 +from myutils.utils import nowisdark from myutils.traceplaytime import playtimemanager from myutils.audioplayer import series_audioplayer from gui.dynalang import LAction, LMenu +from gui.setting_textinput_ocr import showocrimage + class MAINUI: @@ -80,8 +82,26 @@ class MAINUI: self.reader_uid = None self.__hwnd = None self.gameuid = 0 + self.showocrimage = None + self.showocrimage_cached = None self.autoswitchgameuid = True + def maybesetimage(self, pair): + if self.showocrimage: + try: + self.showocrimage.setimage.emit(pair) + except: + print_exc() + self.showocrimage_cached = pair + + def createshowocrimage(self): + try: + self.showocrimage = showocrimage(self.settin_ui, self.showocrimage_cached) + if self.showocrimage: + self.showocrimage.show() + except: + print_exc() + @property def reader(self): return self._internal_reader diff --git a/LunaTranslator/LunaTranslator/gui/setting_display_text.py b/LunaTranslator/LunaTranslator/gui/setting_display_text.py index c35ea478..40edaf24 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_display_text.py +++ b/LunaTranslator/LunaTranslator/gui/setting_display_text.py @@ -1,10 +1,10 @@ from qtsymbols import * import functools, platform -import gobject, os, zipfile, shutil +import gobject, os, zipfile from myutils.config import globalconfig, static_data from gui.inputdialog import multicolorset, autoinitdialog from myutils.wrapper import tryprint -from myutils.utils import dynamiclink, translate_exits +from myutils.utils import dynamiclink, translate_exits, copytree from gui.usefulwidget import ( D_getsimplecombobox, getsimplecombobox, @@ -175,23 +175,6 @@ def createinternalfontsettings(self, forml: LFormLayout, group, _type): ) -def copytree(src, dst, copy_function=shutil.copy2): - names = os.listdir(src) - - os.makedirs(dst, exist_ok=True) - for name in names: - - srcname = os.path.join(src, name) - dstname = os.path.join(dst, name) - try: - if os.path.isdir(srcname): - copytree(srcname, dstname, copy_function) - else: - copy_function(srcname, dstname) - except: - pass - - def doinstallqweb(self, dd, base): if not dd["k"].endswith(base): getQMessageBox(self, "错误", f"请选择_{base}") diff --git a/LunaTranslator/LunaTranslator/gui/setting_textinput_ocr.py b/LunaTranslator/LunaTranslator/gui/setting_textinput_ocr.py index cb6765d3..cd57d246 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_textinput_ocr.py +++ b/LunaTranslator/LunaTranslator/gui/setting_textinput_ocr.py @@ -7,6 +7,7 @@ from gui.usefulwidget import ( D_getsimplecombobox, D_getspinbox, D_getIconButton, + getIconButton, yuitsu_switch, D_getcolorbutton, D_getsimpleswitch, @@ -14,14 +15,15 @@ from gui.usefulwidget import ( getboxlayout, selectcolor, TableViewW, - listediter, + saveposwindow, + pixmapviewer, LStandardItemModel, LFocusCombo, threebuttons, ) -import gobject +import gobject, qtawesome from gui.dynalang import LFormLayout, LDialog, LAction -from myutils.ocrutil import ocr_end, ocr_init +from myutils.ocrutil import ocr_end, ocr_init, ocr_run from myutils.wrapper import threader, Singleton_close @@ -277,6 +279,74 @@ def _ocrparam(self): return self._ocrparam +@Singleton_close +class showocrimage(saveposwindow): + setimage = pyqtSignal(QImage) + + def closeEvent(self, e): + gobject.baseobject.showocrimage = None + super().closeEvent(e) + + def openff(self): + f = QFileDialog.getOpenFileName( + filter="image (" + + " ".join( + ["*" + _.data().decode() for _ in QImageWriter.supportedImageFormats()] + ) + + ")" + ) + res = f[0] + if not res: + return + img = QImage(res) + if img.isNull(): + return + self.originimage = img + self.setimagefunction(img) + text, infotype = ocr_run(img) + if infotype: + gobject.baseobject.displayinfomessage(text, infotype) + else: + gobject.baseobject.textgetmethod(text, False) + + def __init__(self, parent, cached): + self.img1 = None + self.originimage = None + super().__init__(parent, poslist=globalconfig["showocrgeo"]) + self.setWindowIcon(qtawesome.icon("fa.picture-o")) + self.setWindowTitle("截图") + self.originlabel = pixmapviewer() + qw = QWidget() + self.layout1 = QVBoxLayout() + self.setCentralWidget(qw) + qw.setLayout(self.layout1) + icon = getIconButton(callback=self.openff, icon="fa.folder-open") + button = getIconButton(callback=self.retest, icon="fa.rotate-right") + hb = QHBoxLayout() + hb.addWidget(icon) + hb.addWidget(button) + self.layout1.addLayout(hb) + self.layout1.addWidget(self.originlabel) + self.setimage.connect(self.setimagefunction) + if cached: + self.setimagefunction(cached) + + def retest(self): + if self.originimage is None: + return + + text, infotype = ocr_run(self.originimage) + if infotype: + gobject.baseobject.displayinfomessage(text, infotype) + else: + gobject.baseobject.textgetmethod(text, False) + + def setimagefunction(self, originimage): + self.originimage = originimage + self.img1 = QPixmap.fromImage(originimage) + self.originlabel.showpixmap(self.img1) + + def getocrgrid(self): grids = [] @@ -329,7 +399,13 @@ def getocrgrid(self): D_getsimplecombobox( ["横向", "竖向", "自适应"], globalconfig, "verticalocr" ), - ("", 4), + "", + D_getIconButton( + gobject.baseobject.createshowocrimage, + icon="fa.picture-o", + ), + "", + "", ] ], ), diff --git a/LunaTranslator/LunaTranslator/metadata/bangumi.py b/LunaTranslator/LunaTranslator/metadata/bangumi.py index 78385e99..21cec583 100644 --- a/LunaTranslator/LunaTranslator/metadata/bangumi.py +++ b/LunaTranslator/LunaTranslator/metadata/bangumi.py @@ -1,12 +1,12 @@ import requests from myutils.config import savehook_new_data from myutils.utils import initanewitem, gamdidchangedtask -import functools +import functools, time from qtsymbols import * from metadata.abstract import common from gui.usefulwidget import getlineedit from gui.dialog_savedgame import getreflist, getalistname -from myutils.wrapper import Singleton_close +from myutils.wrapper import Singleton_close, threader from gui.dynalang import LPushButton @@ -120,13 +120,41 @@ class bgmsettings(QDialog): def __getalistname(self, callback, _): getalistname(self, callback) + infosig = pyqtSignal(str) + + @threader + def checkvalid(self, k): + t = time.time() + self.tm = t + self._ref.config["access-token"] = k + headers = { + "accept": "application/json", + "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36", + } + headers["Authorization"] = "Bearer " + k + response = requests.get(f"https://api.bgm.tv/v0/me", headers=headers) + description = response.json().get("description", None) + if t != self.tm: + return + if description: + self.setWindowTitle(self._ref.config_all["name"] + " " + description) + else: + + self.setWindowTitle(self._ref.config_all["name"]) + def __init__(self, parent, _ref: common, gameuid: str) -> None: super().__init__(parent, Qt.WindowType.WindowCloseButtonHint) + self.tm = None self._ref = _ref self.resize(QSize(800, 10)) self.setWindowTitle(self._ref.config_all["name"]) fl = QFormLayout(self) - fl.addRow("access-token", getlineedit(_ref.config, "access-token")) + s = QLineEdit() + s.textChanged.connect(self.checkvalid) + s.setText(_ref.config["access-token"]) + + fl.addRow("access-token", s) + btn = LPushButton("上传游戏") btn.clicked.connect( functools.partial(self.singleupload_existsoverride, gameuid) diff --git a/LunaTranslator/LunaTranslator/myutils/ocrutil.py b/LunaTranslator/LunaTranslator/myutils/ocrutil.py index b3ea5125..cecc9801 100644 --- a/LunaTranslator/LunaTranslator/myutils/ocrutil.py +++ b/LunaTranslator/LunaTranslator/myutils/ocrutil.py @@ -6,7 +6,7 @@ from myutils.commonbase import ArgsEmptyExc from myutils.hwnd import screenshot from myutils.utils import stringfyerror from traceback import print_exc -import threading +import threading, gobject def qimage2binary(qimage: QImage, fmt="BMP"): @@ -54,6 +54,7 @@ def imageCut(hwnd, x1, y1, x2, y2) -> QImage: pix = screenshot(x1, y1, x2, y2) image = pix.toImage() + gobject.baseobject.maybesetimage(image) return image diff --git a/LunaTranslator/LunaTranslator/myutils/utils.py b/LunaTranslator/LunaTranslator/myutils/utils.py index 69f29f4f..d399ac65 100644 --- a/LunaTranslator/LunaTranslator/myutils/utils.py +++ b/LunaTranslator/LunaTranslator/myutils/utils.py @@ -835,3 +835,20 @@ class loopbackrecorder: with open(file, "wb") as ff: ff.write(mp3) callback(file) + + +def copytree(src, dst, copy_function=shutil.copy2): + names = os.listdir(src) + + os.makedirs(dst, exist_ok=True) + for name in names: + + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if os.path.isdir(srcname): + copytree(srcname, dstname, copy_function) + else: + copy_function(srcname, dstname) + except: + pass diff --git a/LunaTranslator/LunaTranslator/textsource/texthook.py b/LunaTranslator/LunaTranslator/textsource/texthook.py index 19226bd8..22abf10b 100644 --- a/LunaTranslator/LunaTranslator/textsource/texthook.py +++ b/LunaTranslator/LunaTranslator/textsource/texthook.py @@ -11,11 +11,13 @@ from myutils.config import ( findgameuidofpath, ) from textsource.textsourcebase import basetext -from myutils.utils import checkchaos, getfilemd5, getlangtgt, getlanguagespace +from myutils.utils import checkchaos, getfilemd5, getlangtgt, getlanguagespace, copytree from myutils.hwnd import injectdll, test_injectable, ListProcess, getpidexe from myutils.wrapper import threader from traceback import print_exc -import subprocess +import subprocess, hashlib, requests, zipfile, shutil +from myutils.proxy import getproxy + from ctypes import ( CDLL, @@ -40,6 +42,7 @@ from gui.usefulwidget import getQMessageBox MAX_MODULE_SIZE = 120 HOOK_NAME_SIZE = 60 HOOKCODE_LEN = 500 +oncecheckversion = True class ThreadParam(Structure): @@ -125,7 +128,95 @@ class texthook(basetext): return __shitdict(savehook_new_data[self.gameuid]["hooksetting_private"]) + def tryqueryfromhost(self): + + for i, main_server in enumerate(static_data["main_server"]): + try: + res = requests.get( + "{main_server}/version_lunahook".format(main_server=main_server), + verify=False, + proxies=getproxy(("update", "lunatranslator")), + ) + res = res.json() + return res + except: + pass + + @threader + def checkversion(self): + if not globalconfig["autoupdate"]: + return + dlls = ["LunaHook32.dll", "LunaHook64.dll", "LunaHost32.dll", "LunaHost64.dll"] + sha256 = {} + for dll in dlls: + f = os.path.join("files/plugins/LunaHook", dll) + with open(f, "rb") as ff: + bs = ff.read() + sha = hashlib.sha256(bs).hexdigest() + sha256[dll] = sha + res = self.tryqueryfromhost() + if not res: + return + isnew = True + for _, sha in res["sha256"].items(): + if sha256[_] != sha: + isnew = False + break + if isnew: + return + + url = res["download"] + savep = gobject.getcachedir("update/LunaHook.zip") + if url.startswith("https://github.com"): + __x = "github" + else: + __x = "lunatranslator" + data = requests.get( + url, verify=False, proxies=getproxy(("update", __x)) + ).content + with open(savep, "wb") as ff: + ff.write(data) + tgt = gobject.getcachedir("update/LunaHook") + with zipfile.ZipFile(savep) as zipf: + zipf.extractall(tgt) + if os.path.exists(os.path.join(tgt, "Release_English", "LunaHook32.dll")): + shutil.move(os.path.join(tgt, "Release_English"), "files/plugins/LunaHook") + else: + shutil.move(tgt, "files/plugins/LunaHook") + def init(self): + self.pids = [] + self.keepref = [] + self.hookdatacollecter = OrderedDict() + self.reverse = {} + self.forward = [] + self.selectinghook = None + self.selectedhook = [] + self.selectedhookidx = [] + + self.multiselectedcollector = [] + self.multiselectedcollectorlock = threading.Lock() + self.lastflushtime = 0 + self.runonce_line = "" + gobject.baseobject.autoswitchgameuid = False + self.delaycollectallselectedoutput() + self.autohookmonitorthread() + self.initdllonce = True + self.initdlllock = threading.Lock() + + global oncecheckversion + if oncecheckversion: + oncecheckversion = False + self.checkversion() + + def delayinit(self): + with self.initdlllock: + if not self.initdllonce: + return + self.initdllonce = False + self.__delayinit() + + def __delayinit(self): LunaHost = CDLL( gobject.GetDllpath( ("LunaHost32.dll", "LunaHost64.dll"), @@ -188,23 +279,19 @@ class texthook(basetext): self.Luna_QueryThreadHistory = LunaHost.Luna_QueryThreadHistory self.Luna_QueryThreadHistory.argtypes = (ThreadParam,) self.Luna_QueryThreadHistory.restype = c_void_p - self.pids = [] - self.keepref = [] - self.hookdatacollecter = OrderedDict() - self.reverse = {} - self.forward = [] - self.selectinghook = None - self.selectedhook = [] - self.selectedhookidx = [] - - self.multiselectedcollector = [] - self.multiselectedcollectorlock = threading.Lock() - self.lastflushtime = 0 - self.runonce_line = "" - gobject.baseobject.autoswitchgameuid = False - self.delaycollectallselectedoutput() - self.prepares() - self.autohookmonitorthread() + procs = [ + ProcessEvent(self.onprocconnect), + ProcessEvent(self.removeproc), + ThreadEvent(self.onnewhook), + ThreadEvent(self.onremovehook), + OutputCallback(self.handle_output), + ConsoleHandler(gobject.baseobject.hookselectdialog.sysmessagesignal.emit), + HookInsertHandler(self.newhookinsert), + EmbedCallback(self.getembedtext), + ] + self.keepref += procs + ptrs = [cast(_, c_void_p).value for _ in procs] + self.Luna_Start(*ptrs) def listprocessm(self): cachefname = gobject.gettempdir("{}.txt".format(time.time())) @@ -280,6 +367,7 @@ class texthook(basetext): time.sleep(0.1) def start(self, hwnd, pids, gamepath, gameuid, autostart=False): + self.delayinit() gobject.baseobject.hwnd = hwnd gobject.baseobject.gameuid = gameuid self.gameuid = gameuid @@ -329,23 +417,7 @@ class texthook(basetext): if len(self.pids) == 0: self.autohookmonitorthread() - def prepares(self): - procs = [ - ProcessEvent(self.onprocconnect), - ProcessEvent(self.removeproc), - ThreadEvent(self.onnewhook), - ThreadEvent(self.onremovehook), - OutputCallback(self.handle_output), - ConsoleHandler(gobject.baseobject.hookselectdialog.sysmessagesignal.emit), - HookInsertHandler(self.newhookinsert), - EmbedCallback(self.getembedtext), - ] - self.keepref += procs - ptrs = [cast(_, c_void_p).value for _ in procs] - self.Luna_Start(*ptrs) - def start_unsafe(self, pids): - caninject = test_injectable(pids) injectpids = [] for pid in pids: diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 2b4a8823..6d49e1d6 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -29,7 +29,7 @@ include(generate_product_version) set(VERSION_MAJOR 5) set(VERSION_MINOR 30) -set(VERSION_PATCH 6) +set(VERSION_PATCH 7) add_library(pch pch.cpp) target_precompile_headers(pch PUBLIC pch.h)