This commit is contained in:
恍兮惚兮 2024-06-26 02:05:58 +08:00
parent 20f739a7c7
commit 3f1ce52f05
35 changed files with 875 additions and 865 deletions

View File

@ -6,6 +6,8 @@ from myutils.config import (
globalconfig,
_TR,
savehook_new_list,
uid2gamepath,
gamepath2uid,
savehook_new_data,
setlanguage,
static_data,
@ -407,7 +409,9 @@ class MAINUI:
try:
time.sleep(globalconfig["textthreaddelay"] / 1000)
name = self.textsource.currentname
names = savehook_new_data[self.textsource.pname]["allow_tts_auto_names_v4"]
names = savehook_new_data[self.textsource.gameuid][
"allow_tts_auto_names_v4"
]
needpass = False
if name in names:
needpass = True
@ -438,7 +442,7 @@ class MAINUI:
text = self.ttsrepair(self.currentread, globalconfig["ttscommon"])
try:
text = self.ttsrepair(
text, savehook_new_data[self.textsource.pname]
text, savehook_new_data[self.textsource.gameuid]
)
except:
pass
@ -476,7 +480,8 @@ class MAINUI:
pids, pexe, hwnd = selectedp
checkifnewgame(savehook_new_list, pexe, windows.GetWindowText(hwnd))
if globalconfig["sourcestatus2"]["texthook"]["use"]:
self.textsource = texthook(pids, hwnd, pexe)
self.textsource = texthook(pids, hwnd, pexe, gamepath2uid[pexe])
self.textsource.start()
def starttextsource(self, use=None, checked=True):
self.translation_ui.showhidestate = False
@ -683,7 +688,11 @@ class MAINUI:
hwnd = windows.GetForegroundWindow()
pid = windows.GetWindowThreadProcessId(hwnd)
name_ = getpidexe(pid)
if name_ and name_ in savehook_new_list:
if (
name_
and name_ in gamepath2uid
and gamepath2uid[name_] in savehook_new_list
):
lps = ListProcess(False)
for pids, _exe in lps:
if _exe == name_:
@ -692,23 +701,26 @@ class MAINUI:
self.textsource = None
if globalconfig["sourcestatus2"]["texthook"]["use"]:
if globalconfig["startgamenototop"] == False:
idx = savehook_new_list.index(name_)
idx = savehook_new_list.index(
gamepath2uid[name_]
)
savehook_new_list.insert(
0, savehook_new_list.pop(idx)
)
needinserthookcode = savehook_new_data[name_][
"needinserthookcode"
]
needinserthookcode = savehook_new_data[
gamepath2uid[name_]
]["needinserthookcode"]
self.textsource = texthook(
pids,
hwnd,
name_,
autostarthookcode=savehook_new_data[name_][
"hook"
],
gamepath2uid[name_],
autostarthookcode=savehook_new_data[
gamepath2uid[name_]
]["hook"],
needinserthookcode=needinserthookcode,
)
self.textsource.start()
else:
pids = self.textsource.pids
if sum([int(pid_running(pid)) for pid in pids]) == 0:
@ -778,9 +790,10 @@ class MAINUI:
)
def createsavegamedb(self):
os.makedirs("userconfig", exist_ok=True)
self.sqlsavegameinfo = sqlite3.connect(
"userconfig/savegame.db", check_same_thread=False, isolation_level=None
gobject.getuserconfigdir("savegame.db"),
check_same_thread=False,
isolation_level=None,
)
try:
self.sqlsavegameinfo.execute(
@ -843,21 +856,22 @@ class MAINUI:
savehook_new_data[k].pop("imagepath")
savehook_new_data[k].pop("imagepath_much2")
def querytraceplaytime_v4(self, k):
gameinternalid = self.get_gameinternalid(k)
def querytraceplaytime_v4(self, gameuid):
gameinternalid = self.get_gameinternalid(uid2gamepath[gameuid])
return self.sqlsavegameinfo.execute(
"SELECT timestart,timestop FROM traceplaytime_v4 WHERE gameinternalid = ?",
(gameinternalid,),
).fetchall()
def get_gameinternalid(self, k):
def get_gameinternalid(self, gamepath):
while True:
ret = self.sqlsavegameinfo.execute(
"SELECT gameinternalid FROM gameinternalid WHERE gamepath = ?", (k,)
"SELECT gameinternalid FROM gameinternalid WHERE gamepath = ?",
(gamepath,),
).fetchone()
if ret is None:
self.sqlsavegameinfo.execute(
"INSERT INTO gameinternalid VALUES(NULL,?)", (k,)
"INSERT INTO gameinternalid VALUES(NULL,?)", (gamepath,)
)
else:
return ret[0]
@ -869,9 +883,9 @@ class MAINUI:
(to, _id),
)
def traceplaytime(self, k, start, end, new):
def traceplaytime(self, gamepath, start, end, new):
gameinternalid = self.get_gameinternalid(k)
gameinternalid = self.get_gameinternalid(gamepath)
if new:
self.sqlsavegameinfo.execute(
"INSERT INTO traceplaytime_v4 VALUES(NULL,?,?,?)",
@ -891,16 +905,21 @@ class MAINUI:
time.sleep(1)
_t = time.time()
def isok(name_):
savehook_new_data[name_]["statistic_playtime"] += _t - __t
def isok(gameuid):
savehook_new_data[gameuid]["statistic_playtime"] += _t - __t
if self.__currentexe == name_:
self.traceplaytime(name_, self.__statistictime - 1, _t, False)
self.traceplaytime(
uid2gamepath[gameuid], self.__statistictime - 1, _t, False
)
else:
self.__statistictime = time.time()
self.__currentexe = name_
self.traceplaytime(
name_, self.__statistictime - 1, self.__statistictime, True
uid2gamepath[gameuid],
self.__statistictime - 1,
self.__statistictime,
True,
)
try:
@ -911,13 +930,17 @@ class MAINUI:
if len(self.textsource.pids) == 0:
raise Exception()
if _pid in self.textsource.pids or _pid == os.getpid():
isok(self.textsource.pname)
isok(self.textsource.gameuid)
else:
self.__currentexe = None
except:
name_ = getpidexe(_pid)
if name_ and name_ in savehook_new_list:
isok(name_)
if (
name_
and name_ in gamepath2uid
and gamepath2uid[name_] in savehook_new_list
):
isok(gamepath2uid[name_])
else:
self.__currentexe = None
except:

View File

@ -1,6 +1,6 @@
import requests
from urllib.parse import quote
import re, os
import re, os, gobject
from cishu.cishubase import cishubase
@ -12,15 +12,15 @@ class goo(cishubase):
xx = re.findall("<section>([\\s\\S]*?)</section>", x)
xx = "".join(xx).replace('href="/', 'href="https://dictionary.goo.ne.jp/')
if os.path.exists("cache/temp/goo.css") == False:
temp = gobject.gettempdir("goo.css")
if os.path.exists(temp) == False:
stl = requests.get(
"https://dictionary.goo.ne.jp/mix/css/app.css", proxies=self.proxy
).text
os.makedirs("cache/temp", exist_ok=True)
with open("cache/temp/goo.css", "w", encoding="utf8") as ff:
with open(temp, "w", encoding="utf8") as ff:
ff.write(stl)
else:
with open("cache/temp/goo.css", "r", encoding="utf8") as ff:
with open(temp, "r", encoding="utf8") as ff:
stl = ff.read()
if len(xx):

View File

@ -1,4 +1,4 @@
import math, base64, uuid
import math, base64, uuid, gobject
import threading, time
@ -341,270 +341,12 @@ def rol(s, x):
return (x << s | x >> (32 - s)) & 0xFFFFFFFF
r = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9,
10,
11,
12,
13,
14,
15,
7,
4,
13,
1,
10,
6,
15,
3,
12,
0,
9,
5,
2,
14,
11,
8,
3,
10,
14,
4,
9,
15,
8,
1,
2,
7,
0,
6,
13,
11,
5,
12,
1,
9,
11,
10,
0,
8,
12,
4,
13,
3,
7,
15,
14,
5,
6,
2,
]
rp = [
5,
14,
7,
0,
9,
2,
11,
4,
13,
6,
15,
8,
1,
10,
3,
12,
6,
11,
3,
7,
0,
13,
5,
10,
14,
15,
8,
12,
4,
9,
1,
2,
15,
5,
1,
3,
7,
14,
6,
9,
11,
8,
12,
2,
10,
0,
4,
13,
8,
6,
4,
1,
3,
11,
15,
0,
5,
12,
2,
13,
9,
7,
10,
14,
]
s = [
11,
14,
15,
12,
5,
8,
7,
9,
11,
13,
14,
15,
6,
7,
9,
8,
7,
6,
8,
13,
11,
9,
7,
15,
7,
12,
15,
9,
11,
7,
13,
12,
11,
13,
6,
7,
14,
9,
13,
15,
14,
8,
13,
6,
5,
12,
7,
5,
11,
12,
14,
15,
14,
15,
9,
8,
9,
14,
5,
6,
8,
6,
5,
12,
]
sp = [
8,
9,
9,
11,
13,
15,
15,
5,
7,
7,
8,
11,
14,
14,
12,
6,
9,
13,
15,
7,
12,
8,
9,
11,
7,
7,
12,
7,
6,
15,
13,
11,
9,
7,
15,
11,
8,
6,
6,
14,
12,
13,
5,
14,
13,
13,
7,
5,
15,
5,
8,
11,
14,
14,
6,
14,
6,
9,
12,
9,
12,
5,
15,
8,
]
# fmt: off
r = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 7, 4, 13, 1, 10, 6, 15, 3, 12, 0, 9, 5, 2, 14, 11, 8, 3, 10, 14, 4, 9, 15, 8, 1, 2, 7, 0, 6, 13, 11, 5, 12, 1, 9, 11, 10, 0, 8, 12, 4, 13, 3, 7, 15, 14, 5, 6, 2]
rp = [ 5, 14, 7, 0, 9, 2, 11, 4, 13, 6, 15, 8, 1, 10, 3, 12, 6, 11, 3, 7, 0, 13, 5, 10, 14, 15, 8, 12, 4, 9, 1, 2, 15, 5, 1, 3, 7, 14, 6, 9, 11, 8, 12, 2, 10, 0, 4, 13, 8, 6, 4, 1, 3, 11, 15, 0, 5, 12, 2, 13, 9, 7, 10, 14]
s = [ 11, 14, 15, 12, 5, 8, 7, 9, 11, 13, 14, 15, 6, 7, 9, 8, 7, 6, 8, 13, 11, 9, 7, 15, 7, 12, 15, 9, 11, 7, 13, 12, 11, 13, 6, 7, 14, 9, 13, 15, 14, 8, 13, 6, 5, 12, 7, 5, 11, 12, 14, 15, 14, 15, 9, 8, 9, 14, 5, 6, 8, 6, 5, 12]
sp = [ 8, 9, 9, 11, 13, 15, 15, 5, 7, 7, 8, 11, 14, 14, 12, 6, 9, 13, 15, 7, 12, 8, 9, 11, 7, 7, 12, 7, 6, 15, 13, 11, 9, 7, 15, 11, 8, 6, 6, 14, 12, 13, 5, 14, 13, 13, 7, 5, 15, 5, 8, 11, 14, 14, 6, 14, 6, 9, 12, 9, 12, 5, 15, 8]
# fmt: on
def ripemd128(message):
@ -1962,13 +1704,12 @@ class IndexBuilder(object):
_filename, _file_extension = os.path.splitext(fname)
assert _file_extension == ".mdx"
assert os.path.isfile(fname)
os.makedirs("cache/mdict/index", exist_ok=True)
_mdxmd5 = (
os.path.basename(_filename)
+ "_"
+ hashlib.md5(_filename.encode("utf8")).hexdigest()
)
_targetfilenamebase = os.path.join("cache/mdict/index", _mdxmd5)
_targetfilenamebase = gobject.getcachedir("mdict/index/" + _mdxmd5)
self._mdx_db = _targetfilenamebase + ".mdx.db"
# make index anyway
if force_rebuild:
@ -2363,7 +2104,9 @@ class mdict(cishubase):
self.init_once_mdx(f)
try:
with open("userconfig/mdict_config.json", "w", encoding="utf8") as ff:
with open(
gobject.getuserconfigdir("mdict_config.json"), "w", encoding="utf8"
) as ff:
ff.write(json.dumps(self.extraconf, ensure_ascii=False, indent=4))
except:
pass

View File

@ -15,6 +15,30 @@ def GetDllpath(_, base=None):
return os.path.join(base, _[isbit64])
def getcachedir(name, basedir="cache"):
fd = os.path.dirname(name)
fn = os.path.basename(name)
fn1 = os.path.abspath(basedir)
fn1 = os.path.join(fn1, fd)
os.makedirs(fn1, exist_ok=True)
fn1 = os.path.join(fn1, fn)
return fn1
def getuserconfigdir(name):
return getcachedir(name, "userconfig")
def gettranslationrecorddir(name):
return getcachedir(name, "translation_record")
def gettempdir(filename):
tgt = getcachedir(os.path.join(f"temp{os.getpid()}", filename))
return tgt
def dopathexists(file):
if not file:
return False

View File

@ -1,5 +1,5 @@
from qtsymbols import *
import os
import os, gobject
from myutils.config import _TR, globalconfig
from myutils.wrapper import Singleton_close
from gui.usefulwidget import saveposwindow
@ -30,8 +30,7 @@ class dialog_memory(saveposwindow):
self.gamemd5 = gamemd5
formLayout = QVBoxLayout() #
self.showtext = QTextEdit()
os.makedirs("./userconfig/memory", exist_ok=True)
self.rwpath = "./userconfig/memory/{}.html".format(gamemd5)
self.rwpath = gobject.getuserconfigdir("memory/{}.html".format(gamemd5))
try:
with open(self.rwpath, "r", encoding="utf8") as ff:
text = ff.read()

File diff suppressed because it is too large Load Diff

View File

@ -95,7 +95,7 @@ def sqlite2json2(self, sqlitefile, targetjson=None, existsmerge=False):
for k in existsjs:
if k not in js_format2 or js_format2[k] == "":
js_format2[k] = existsjs[k]
os.makedirs(os.path.dirname(target), exist_ok=True)
with open(target, "w", encoding="utf8") as ff:
ff.write(
json.dumps(js_format2, ensure_ascii=False, sort_keys=False, indent=4)
@ -109,8 +109,7 @@ def sqlite2json2(self, sqlitefile, targetjson=None, existsmerge=False):
def sqlite2json(self):
os.makedirs("./translation_record", exist_ok=True)
f = QFileDialog.getOpenFileName(directory="./translation_record", filter="*.sqlite")
f = QFileDialog.getOpenFileName(directory="translation_record", filter="*.sqlite")
if f[0] == "":
return

View File

@ -74,8 +74,7 @@ class QButtonGroup_switch_widegt(QWidget):
def listprocessm():
os.makedirs("cache/temp", exist_ok=True)
cachefname = os.path.abspath("cache/temp/{}.txt".format(time.time()))
cachefname = gobject.gettempdir("{}.txt".format(time.time()))
arch = "64" if gobject.baseobject.textsource.is64bit else "32"
exe = os.path.abspath("./files/plugins/shareddllproxy{}.exe".format(arch))
pid = " ".join([str(_) for _ in gobject.baseobject.textsource.pids])
@ -211,7 +210,7 @@ class searchhookparam(QDialog):
layout1 = QHBoxLayout()
layout1.addWidget(QLabel(_TR("代码页")))
self.codepagesave = {
"spcp": savehook_new_data[gobject.baseobject.textsource.pname].get(
"spcp": savehook_new_data[gobject.baseobject.textsource.gameuid].get(
"codepage_index", globalconfig["codepage_index"]
)
}
@ -513,7 +512,7 @@ class hookselect(closeashidewindow):
gobject.baseobject.textsource.hooktypecollecter,
key,
callback=functools.partial(
savehook_new_data[gobject.baseobject.textsource.pname][
savehook_new_data[gobject.baseobject.textsource.gameuid][
"hooktypeasname"
].__setitem__,
json.dumps(gobject.baseobject.textsource.serialkey(key)),
@ -537,10 +536,10 @@ class hookselect(closeashidewindow):
if hn[:8] == "UserHook":
needinserthookcode = savehook_new_data[
gobject.baseobject.textsource.pname
gobject.baseobject.textsource.gameuid
]["needinserthookcode"]
needinserthookcode = list(set(needinserthookcode + [hc]))
savehook_new_data[gobject.baseobject.textsource.pname].update(
savehook_new_data[gobject.baseobject.textsource.gameuid].update(
{"needinserthookcode": needinserthookcode}
)
else:
@ -552,19 +551,19 @@ class hookselect(closeashidewindow):
gobject.baseobject.textsource.useembed(tp.addr, tp.ctx, tp.ctx2, _)
_use = self._check_tp_using(key)
if _use:
savehook_new_data[gobject.baseobject.textsource.pname][
savehook_new_data[gobject.baseobject.textsource.gameuid][
"embedablehook"
].append([hc, tp.addr, tp.ctx, tp.ctx2])
else:
save = []
for _ in savehook_new_data[gobject.baseobject.textsource.pname][
for _ in savehook_new_data[gobject.baseobject.textsource.gameuid][
"embedablehook"
]:
hc, ad, c1, c2 = _
if (hc, 0, c1, c2) == (hc, 0, tp.ctx, tp.ctx2):
save.append(_)
for _ in save:
savehook_new_data[gobject.baseobject.textsource.pname][
savehook_new_data[gobject.baseobject.textsource.gameuid][
"embedablehook"
].remove(_)
@ -710,7 +709,7 @@ class hookselect(closeashidewindow):
def opengamesetting(self):
try:
dialog_setting_game(self, gobject.baseobject.textsource.pname, True)
dialog_setting_game(self, gobject.baseobject.textsource.gameuid, True)
except:
print_exc()
@ -865,16 +864,16 @@ class hookselect(closeashidewindow):
if hn[:8] == "UserHook":
needinserthookcode = savehook_new_data[
gobject.baseobject.textsource.pname
gobject.baseobject.textsource.gameuid
]["needinserthookcode"]
needinserthookcode = list(set(needinserthookcode + [hc]))
savehook_new_data[gobject.baseobject.textsource.pname].update(
savehook_new_data[gobject.baseobject.textsource.gameuid].update(
{"needinserthookcode": needinserthookcode}
)
else:
pass
savehook_new_data[gobject.baseobject.textsource.pname].update(
savehook_new_data[gobject.baseobject.textsource.gameuid].update(
{"hook": gobject.baseobject.textsource.serialselectedhook()}
)
except:

View File

@ -52,8 +52,10 @@ def doupdate():
elif platform.architecture()[0] == "32bit":
bit = "_x86"
_6432 = "32"
os.makedirs("./cache", exist_ok=True)
shutil.copy(rf".\files\plugins\shareddllproxy{_6432}.exe", rf".\cache\Updater.exe")
shutil.copy(
rf".\files\plugins\shareddllproxy{_6432}.exe",
gobject.getcachedir("Updater.exe"),
)
subprocess.Popen(rf".\cache\Updater.exe update .\cache\update\LunaTranslator{bit}")
@ -82,9 +84,7 @@ def updatemethod(_version, self):
_version, bit
)
savep = "./cache/update/LunaTranslator{}.zip".format(bit)
os.makedirs("./cache/update", exist_ok=True)
savep = gobject.getcachedir("update/LunaTranslator{}.zip".format(bit))
r2 = requests.get(
url, stream=True, verify=False, proxies=getproxy(("github", "download"))
@ -124,11 +124,9 @@ def updatemethod(_version, self):
def uncompress(self, savep):
self.progresssignal.emit("正在解压……", 10000)
os.makedirs("./cache/update", exist_ok=True)
if os.path.exists("./cache/update/LunaTranslator"):
shutil.rmtree("./cache/update/LunaTranslator")
shutil.rmtree(gobject.getcachedir("update/LunaTranslator"))
with zipfile.ZipFile(savep) as zipf:
zipf.extractall("./cache/update")
zipf.extractall(gobject.getcachedir("update"))
@threader

View File

@ -72,8 +72,9 @@ class extrahtml(saveposwindow):
)
def savehtml(self):
os.makedirs("userconfig", exist_ok=True)
with open("userconfig/extrahtml.html", "w", encoding="utf8") as ff:
with open(
gobject.getuserconfigdir("extrahtml.html"), "w", encoding="utf8"
) as ff:
ff.write(self.vistext.toPlainText())
def __init__(self, parent) -> None:
@ -188,8 +189,7 @@ def doinstallqweb(self, dd, base):
getQMessageBox(self, "错误", f"请选择_{base}")
return
with zipfile.ZipFile(dd["k"]) as zipf:
target = "cache/temp/QWebEngine"
os.makedirs(target, exist_ok=True)
target = gobject.gettempdir("QWebEngine/")
zipf.extractall(target)
bit = ["x86", "x64"][platform.architecture()[0] == "64bit"]
copytree(f"{target}/{bit}/PyQt5", "LunaTranslator/runtime/PyQt5")

View File

@ -7,6 +7,7 @@ from myutils.config import (
_TR,
_TRL,
savehook_new_data,
uid2gamepath,
savehook_new_list,
static_data,
)
@ -176,7 +177,7 @@ def gethookgrid(self):
return grids
def doexportchspatch(exe, realgame):
def doexportchspatch(exe, gameuid):
b = windows.GetBinaryType(exe)
is64 = b == 6
@ -199,10 +200,10 @@ def doexportchspatch(exe, realgame):
embedconfig = {
"translation_file": "translation.json",
"target_exe": os.path.basename(exe),
"target_exe2": os.path.basename(realgame),
"target_exe2": os.path.basename(exe),
"startup_argument": None,
"inject_timeout": 1000,
"embedhook": savehook_new_data[realgame]["embedablehook"],
"embedhook": savehook_new_data[gameuid]["embedablehook"],
"embedsettings": {
"font": (
globalconfig["embedded"]["changefont_font"]
@ -219,7 +220,7 @@ def doexportchspatch(exe, realgame):
ff.write(json.dumps(embedconfig, ensure_ascii=False, indent=4))
def getunknowgameexe(self):
def selectgameuid(self):
dialog = QDialog(self, Qt.WindowType.WindowCloseButtonHint) # 自定义一个dialog
dialog.setWindowTitle(_TR("选择游戏"))
@ -245,10 +246,10 @@ def getunknowgameexe(self):
def exportchspatch(self):
realgame = getunknowgameexe(self)
if realgame is None:
gameuid = selectgameuid(self)
if gameuid is None:
return
exe = realgame
exe = uid2gamepath[gameuid]
if exe.lower().endswith(".exe") == False:
f = QFileDialog.getOpenFileName(
self, caption=_TR("选择EXE文件"), filter="*.exe"
@ -257,16 +258,15 @@ def exportchspatch(self):
if exe == "":
return
exe = os.path.normpath(exe)
doexportchspatch(exe, realgame)
doexportchspatch(exe, gameuid)
md5 = getfilemd5(exe)
name = os.path.basename(exe).replace("." + os.path.basename(exe).split(".")[-1], "")
os.makedirs("./translation_record", exist_ok=True)
sqlfname_all = "./translation_record/" + name + "_" + md5 + ".sqlite"
sqlfname_all = gobject.gettranslationrecorddir(name + "_" + md5 + ".sqlite")
if os.path.exists(sqlfname_all) == False:
f = QFileDialog.getOpenFileName(
self,
caption=_TR("选择预翻译文件"),
directory="./translation_record/",
directory="translation_record",
filter="*.sqlite",
)
sqlfname_all = f[0]
@ -388,10 +388,10 @@ def getTabclip(self):
grids = [
[
"排除复制自翻译器的文本",
"排除复制自翻译器的文本",
D_getsimpleswitch(globalconfig, "excule_from_self"),
"",
""
"",
]
]
return grids

View File

@ -6,7 +6,7 @@ import qtawesome, requests, gobject, windows
import myutils.ankiconnect as anki
from myutils.hwnd import grabwindow
from myutils.utils import parsekeystringtomodvkcode, unsupportkey
from myutils.config import globalconfig, _TR, static_data
from myutils.config import globalconfig, _TR, static_data, savehook_new_data
from myutils.subproc import subproc_w
from myutils.wrapper import threader
from myutils.ocrutil import imageCut, ocr_run
@ -39,12 +39,10 @@ def getimageformat():
return getimageformatlist()[globalconfig["imageformat"]]
class loopbackrecorder:
def __init__(self):
os.makedirs("cache/temp", exist_ok=True)
self.file = os.path.abspath(
os.path.join("cache/temp", str(time.time()) + ".wav")
)
self.file = gobject.gettempdir(str(time.time()) + ".wav")
try:
self.waitsignal = str(time.time())
self.engine = subproc_w(
@ -112,8 +110,7 @@ class AnkiWindow(QWidget):
refreshhtml = pyqtSignal()
def callbacktts(self, edit, data):
fname = "cache/temp/" + str(uuid.uuid4()) + ".mp3"
os.makedirs("cache/temp", exist_ok=True)
fname = gobject.gettempdir(str(uuid.uuid4()) + ".mp3")
with open(fname, "wb") as ff:
ff.write(data)
edit.setText(os.path.abspath(fname))
@ -140,8 +137,7 @@ class AnkiWindow(QWidget):
img = imageCut(
0, rect[0][0], rect[0][1], rect[1][0], rect[1][1], False, True
)
fname = "cache/temp/" + str(uuid.uuid4()) + "." + getimageformat()
os.makedirs("cache/temp", exist_ok=True)
fname = gobject.gettempdir(str(uuid.uuid4()) + "." + getimageformat())
img.save(fname)
self.editpath.setText(os.path.abspath(fname))
if globalconfig["ankiconnect"]["ocrcroped"]:
@ -337,12 +333,17 @@ class AnkiWindow(QWidget):
model_htmlfront = self.fronttext.toPlainText()
model_htmlback = self.backtext.toPlainText()
model_css = self.csstext.toPlainText()
os.makedirs("userconfig/anki", exist_ok=True)
with open("userconfig/anki/back.html", "w", encoding="utf8") as ff:
with open(
gobject.getuserconfigdir("anki/back.html"), "w", encoding="utf8"
) as ff:
ff.write(model_htmlback)
with open("userconfig/anki/front.html", "w", encoding="utf8") as ff:
with open(
gobject.getuserconfigdir("anki/front.html"), "w", encoding="utf8"
) as ff:
ff.write(model_htmlfront)
with open("userconfig/anki/style.css", "w", encoding="utf8") as ff:
with open(
gobject.getuserconfigdir("anki/style.css"), "w", encoding="utf8"
) as ff:
ff.write(model_css)
def creatsetdtab(self, baselay):
@ -431,14 +432,34 @@ class AnkiWindow(QWidget):
@threader
def simulate_key(self, i):
if not globalconfig["ankiconnect"]["simulate_key"][i]["use"]:
def __internal__keystring(i):
try:
for _ in (0,):
if not gobject.baseobject.textsource:
break
gameuid = gobject.baseobject.textsource.gameuid
if not gameuid:
break
if savehook_new_data[gameuid]["follow_default_ankisettings"]:
break
if not savehook_new_data[gameuid][f"anki_simulate_key_{i}_use"]:
return None
return savehook_new_data[gameuid][
f"anki_simulate_key_{i}_keystring"
]
except:
pass
return globalconfig["ankiconnect"]["simulate_key"][i]["keystring"]
keystring = __internal__keystring(i)
if not keystring:
return
windows.SetForegroundWindow(gobject.baseobject.textsource.hwnd)
time.sleep(0.1)
try:
modes, vkcode = parsekeystringtomodvkcode(
globalconfig["ankiconnect"]["simulate_key"][i]["keystring"], modes=True
)
modes, vkcode = parsekeystringtomodvkcode(keystring, modes=True)
except unsupportkey as e:
print("不支持的键")
return
@ -593,7 +614,9 @@ class AnkiWindow(QWidget):
or pix.height() > self.viewimagelabel.height()
):
pix = pix.scaled(
self.viewimagelabel.size() * rate, Qt.AspectRatioMode.KeepAspectRatio
self.viewimagelabel.size() * rate,
Qt.AspectRatioMode.KeepAspectRatio,
Qt.TransformationMode.SmoothTransformation,
)
self.viewimagelabel.setPixmap(pix)
@ -650,11 +673,30 @@ class AnkiWindow(QWidget):
return model_htmlfront, model_htmlback, model_css
def addanki(self):
def __internal__DeckName():
try:
for _ in (0,):
if not gobject.baseobject.textsource:
break
gameuid = gobject.baseobject.textsource.gameuid
if not gameuid:
break
if savehook_new_data[gameuid]["follow_default_ankisettings"]:
break
return savehook_new_data[gameuid]["anki_DeckName"]
except:
pass
return globalconfig["ankiconnect"]["DeckName"]
autoUpdateModel = globalconfig["ankiconnect"]["autoUpdateModel"]
allowDuplicate = globalconfig["ankiconnect"]["allowDuplicate"]
anki.global_port = globalconfig["ankiconnect"]["port"]
ModelName = globalconfig["ankiconnect"]["ModelName5"]
DeckName = globalconfig["ankiconnect"]["DeckName"]
DeckName = __internal__DeckName()
model_htmlfront, model_htmlback, model_css = self.tryloadankitemplates()
tags = globalconfig["ankiconnect"]["tags"]
anki.Deck.create(DeckName)

View File

@ -474,7 +474,6 @@ class delayloadvbox(QWidget):
self.lock = threading.Lock()
self.nowvisregion = QRect()
def resizeEvent(self, e: QResizeEvent):
if e.oldSize().width() != e.size().width():
@ -483,6 +482,7 @@ class delayloadvbox(QWidget):
if isinstance(w, QWidget):
w.resize(self.width(), w.height())
return super().resizeEvent(e)
def _dovisinternal(self, procevent, region: QRect):
if region.isEmpty():
return
@ -544,6 +544,12 @@ class delayloadvbox(QWidget):
# setFixedHeight会导致上面的闪烁
self._dovisinternal(False, self.nowvisregion)
def torank1(self, i):
with self.lock:
self.internal_widgets.insert(0, self.internal_widgets.pop(i))
self.internal_itemH.insert(0, self.internal_itemH.pop(i))
self._dovisinternal(False, self.nowvisregion)
def insertw(self, i, wf, height):
refresh = True
with self.lock:
@ -597,6 +603,9 @@ class shrinkableitem(QWidget):
def insertw(self, i, wf, height):
self.items.insertw(i, wf, height)
def torank1(self, i):
self.items.torank1(i)
def popw(self, i):
return self.items.popw(i)

View File

@ -3,11 +3,11 @@ import time, functools, threading, os, sys, importlib, shutil
from traceback import print_exc
import windows, qtawesome, gobject, winsharedutils
from myutils.wrapper import threader, trypass
from myutils.config import globalconfig, saveallconfig, _TR, static_data
from myutils.config import globalconfig, saveallconfig, _TR, static_data, gamepath2uid
from myutils.subproc import endsubprocs
from myutils.ocrutil import ocr_run, imageCut
from myutils.utils import loadpostsettingwindowmethod, str2rgba
from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon
from myutils.hwnd import mouseselectwindow, grabwindow, getExeIcon, getpidexe
from gui.setting_about import doupdate
from gui.dialog_memory import dialog_memory
from gui.textbrowser import Textbrowser
@ -381,7 +381,7 @@ class QUnFrameWindow(resizableframeless):
"open_relative_link",
lambda: browserdialog(
gobject.baseobject.commonstylebase,
trypass(lambda: gobject.baseobject.textsource.pname)(),
trypass(lambda: gobject.baseobject.textsource.gameuid)(),
),
),
(
@ -797,6 +797,9 @@ class QUnFrameWindow(resizableframeless):
gobject.baseobject.textsource.hwnd = hwnd if pid != _pid else None
if not globalconfig["sourcestatus2"]["texthook"]["use"]:
gobject.baseobject.textsource.pids = [pid] if pid != _pid else None
gameuid = gamepath2uid.get(getpidexe(pid), None)
if gameuid:
gobject.baseobject.textsource.gameuid = gameuid
self.isbindedwindow = pid != _pid
self.refreshtoolicon()
@ -1007,7 +1010,7 @@ class QUnFrameWindow(resizableframeless):
def tryremoveuseless(self):
try:
shutil.rmtree("./cache/temp")
shutil.rmtree(gobject.gettempdir(''))
except:
pass
try:

View File

@ -920,8 +920,7 @@ class abstractwebview(QWidget):
if len(html) < self.html_limit:
self._setHtml(html)
else:
os.makedirs("cache/temp", exist_ok=True)
lastcachehtml = os.path.abspath("cache/temp/" + str(time.time()) + ".html")
lastcachehtml = gobject.gettempdir(str(time.time()) + ".html")
with open(lastcachehtml, "w", encoding="utf8") as ff:
ff.write(html)
self.navigate(lastcachehtml)
@ -1665,9 +1664,9 @@ class listediter(QDialog):
if self.closecallback:
self.closecallback()
def __cb(self, path):
self.hcmodel.insertRow(0, [QStandardItem(path)])
def __cb(self, paths):
for path in paths:
self.hcmodel.insertRow(0, [QStandardItem(path)])
def click1(self):
@ -1676,7 +1675,7 @@ class listediter(QDialog):
else:
openfiledirectory(
"",
multi=False,
multi=True,
edit=None,
isdir=self.ispathsedit.get("isdir", False),
filter1=self.ispathsedit.get("filter1", "*.*"),

View File

@ -45,19 +45,24 @@ class common:
Thread(target=self.__autodownloadimage).start()
def __autodownloadimage(self):
def tryremove(pair):
try:
globalconfig["metadata"][self.typename]["downloadtasks"].remove(
list(pair)
)
except:
pass
while True:
url, save = self.__tasks.get()
pair = self.__tasks.get()
url, save = pair
if os.path.exists(save):
tryremove(pair)
continue
if self.__realdodownload(url, save):
try:
globalconfig["metadata"][self.typename]["downloadtasks"].remove(
(url, save)
)
except:
pass
tryremove(pair)
else:
self.__tasks.put((url, save))
self.__tasks.put(pair)
time.sleep(1)
def __realdodownload(self, url, save):
@ -73,36 +78,27 @@ class common:
}
try:
_content = self.proxysession.get(url, headers=headers).content
os.makedirs(os.path.dirname(save), exist_ok=True)
with open(save, "wb") as ff:
ff.write(_content)
return True
except:
return False
def dispatchdownloadtask(self, url, ishtml=False, delay=True):
def dispatchdownloadtask(self, url):
__routine = f"cache/metadata/{self.typename}"
if self.typename == "vndb":
__routine = "cache/vndb"
os.makedirs(__routine, exist_ok=True)
if ishtml:
__ = ".html"
if "." in url[5:]:
__ = url[url.rfind(".") :]
else:
if "." in url[5:]:
__ = url[url.rfind(".") :]
else:
__ = ".jpg"
__ = ".jpg"
savepath = f"{__routine}/{self.b64string(url)}{__}"
if delay:
globalconfig["metadata"][self.typename]["downloadtasks"].append(
(url, savepath)
)
self.__tasks.put((url, savepath))
return savepath
else:
if self.__realdodownload(url, savepath):
return savepath
else:
return None
globalconfig["metadata"][self.typename]["downloadtasks"].append((url, savepath))
self.__tasks.put((url, savepath))
return savepath
def b64string(self, a):
return hashlib.md5(a.encode("utf8")).hexdigest()

View File

@ -1,7 +1,7 @@
import requests, re, os
from myutils.config import tryreadconfig, safesave
import gzip, json
import shutil
import shutil, gobject
from metadata.abstract import common
@ -156,14 +156,12 @@ def safedownload(proxy):
"https://dl.vndb.org/dump/vndb-tags-latest.json.gz",
proxies=proxy,
)
os.makedirs("cache/temp", exist_ok=True)
with open("cache/temp/vndb-tags-latest.json.gz", "wb") as ff:
jsongz = gobject.gettempdir("vndb-tags-latest.json.gz")
jsonfile = gobject.gettempdir("vndb-tags-latest.json")
with open(jsongz, "wb") as ff:
ff.write(resp.content)
decompress_gzip_file(
"cache/temp/vndb-tags-latest.json.gz",
"cache/temp/vndb-tags-latest.json",
)
with open("cache/temp/vndb-tags-latest.json", "r", encoding="utf8") as ff:
decompress_gzip_file(jsongz, jsonfile)
with open(jsonfile, "r", encoding="utf8") as ff:
js = json.load(ff)
newjs = {}
for item in js:
@ -215,18 +213,6 @@ def getvntagsbyid(proxy, vid):
return tags
def gettagfromhtml(path):
if path and os.path.exists(path):
with open(path, "r", encoding="utf8") as ff:
html = ff.read()
find = re.search('<div id="vntags">([\\s\\S]*?)</div>', html)
if find:
html = find.groups()[0]
return [_[1] for _ in re.findall("<a(.*?)>(.*?)</a>", html)]
return []
class searcher(common):
def refmainpage(self, _id):
@ -238,8 +224,27 @@ class searcher(common):
return int(vid[1:])
return None
def gettagfromhtml(self, _vid):
headers = {
"sec-ch-ua": '"Microsoft Edge";v="113", "Chromium";v="113", "Not-A.Brand";v="24"',
"Referer": "https://vndb.org/",
"sec-ch-ua-mobile": "?0",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36 Edg/113.0.1774.42",
"sec-ch-ua-platform": '"Windows"',
}
try:
html = self.proxysession.get(self.refmainpage(_vid), headers=headers).text
except:
return []
find = re.search('<div id="vntags">([\\s\\S]*?)</div>', html)
if find:
html = find.groups()[0]
return [_[1] for _ in re.findall("<a(.*?)>(.*?)</a>", html)]
else:
return []
def searchfordata(self, _vid):
os.makedirs("./cache/vndb", exist_ok=True)
vid = "v{}".format(_vid)
img = getimgbyid(self.proxy, vid)
title = gettitlebyid(self.proxy, vid)
@ -247,11 +252,7 @@ class searcher(common):
vndbtags = [] # getvntagsbyid(self.proxy, vid) #这个东西谜之慢
if len(vndbtags) == 0:
# 没代理时下不动那个tag的json
vndbtags = gettagfromhtml(
self.dispatchdownloadtask(
self.refmainpage(_vid), ishtml=True, delay=False
)
)
vndbtags = self.gettagfromhtml(_vid)
developers = getdevelopersbyid(self.proxy, vid)
try:
imagepath_much2 = [

View File

@ -4,22 +4,23 @@ from traceback import print_exc
def tryreadconfig(path, default=None):
path = os.path.join("userconfig", path)
if not os.path.exists(path):
path += ".tmp"
dfret = default if default else {}
if not os.path.exists(path):
return dfret
try:
path = os.path.join("./userconfig/", path)
if os.path.exists(path) == False:
path += ".tmp"
if os.path.exists(path):
with open(path, "r", encoding="utf-8") as ff:
x = json.load(ff)
else:
x = default if default else {}
with open(path, "r", encoding="utf-8") as ff:
x = json.load(ff)
return x
except:
return {}
return dfret
def tryreadconfig2(path):
path = os.path.join("./files/defaultconfig/", path)
path = os.path.join("files/defaultconfig", path)
with open(path, "r", encoding="utf-8") as ff:
x = json.load(ff)
return x
@ -41,25 +42,67 @@ magpie_config = tryreadconfig("magpie_config.json")
postprocessconfig = tryreadconfig("postprocessconfig.json")
noundictconfig = tryreadconfig("noundictconfig.json")
transerrorfixdictconfig = tryreadconfig("transerrorfixdictconfig.json")
_savehook = tryreadconfig("savehook_new_1.39.4.json", default=[[], {}])
try:
_savehook = tryreadconfig("savegamedata_5.3.1.json")
if _savehook:
# 新版
# savehook_new_list: [uid,...]
# savehook_new_data:{uid:dict,...}
# savegametaged:[ None, {'games':[uid,...],'title':str,'opened':bool,'uid':str},...]
# gamepath2uid:{gamepath:uid}
savehook_new_list = _savehook[0]
savehook_new_data = _savehook[1]
except:
savehook_new_list = []
savehook_new_data = {}
try:
savegametaged = _savehook[2]
except:
savegametaged = [None]
gamepath2uid = _savehook[3]
else:
_savehook = tryreadconfig("savehook_new_1.39.4.json", default=[[], {}])
# savehook_new_list: [gamepath,...]
# savehook_new_data:{gamepath:dict,...}
# savegametaged: 可能没有该项 [ None, {'games':[gamepath,...],'title':str,'opened':bool,'uid':str},...]
try:
savehook_new_list = _savehook[0]
savehook_new_data = _savehook[1]
except:
savehook_new_list = []
savehook_new_data = {}
try:
savegametaged = _savehook[2]
except:
savegametaged = [None]
# 将savehook_new_data转换为新的格式
gamepath2uid = {}
__savehook_new_data = {}
for k in savehook_new_data:
uid = f"{time.time()}_{uuid.uuid4()}"
__savehook_new_data[uid] = savehook_new_data[k]
__savehook_new_data[uid].update(gamepath=k)
gamepath2uid[k] = uid
savehook_new_data = __savehook_new_data
# 将global游戏表和自定义子列表都转换成新格式
def parselist(ls):
for i in range(len(ls)):
ori = ls[i]
if ori not in gamepath2uid:
continue
ls[i] = gamepath2uid[ori]
parselist(savehook_new_list)
for sub in savegametaged:
if sub is None:
continue
parselist(sub["games"])
translatorsetting = tryreadconfig("translatorsetting.json")
ocrsetting = tryreadconfig("ocrsetting.json")
def getdefaultsavehook(gamepath, title=None):
default = {
# "gamepath": gamepath,
"hooksetting_follow_default": True,
"hooksetting_private": {}, # 显示时再加载缺省用global中的键
"textproc_follow_default": True,
@ -71,6 +114,8 @@ def getdefaultsavehook(gamepath, title=None):
"lang_follow_default": True,
# "private_srclang": 0,# 显示时再加载缺省用global中的键
# "private_tgtlang": 0,
"follow_default_ankisettings": True,
# "anki_DeckName":str
"localeswitcher": 0,
"onloadautochangemode2": 0,
"needinserthookcode": [],
@ -132,19 +177,31 @@ def getdefaultsavehook(gamepath, title=None):
_dfsavehook = getdefaultsavehook("")
for game in savehook_new_data:
for uid in savehook_new_data:
if (
("allow_tts_auto_names_v4" not in savehook_new_data[game])
and ("allow_tts_auto_names" in savehook_new_data[game])
and len(savehook_new_data[game]["allow_tts_auto_names"])
("allow_tts_auto_names_v4" not in savehook_new_data[uid])
and ("allow_tts_auto_names" in savehook_new_data[uid])
and len(savehook_new_data[uid]["allow_tts_auto_names"])
):
savehook_new_data[game]["allow_tts_auto_names_v4"] = savehook_new_data[game][
savehook_new_data[uid]["allow_tts_auto_names_v4"] = savehook_new_data[uid][
"allow_tts_auto_names"
].split("|")
for k in _dfsavehook:
if k not in savehook_new_data[game]:
savehook_new_data[game][k] = _dfsavehook[k]
if k not in savehook_new_data[uid]:
savehook_new_data[uid][k] = _dfsavehook[k]
class __uid2gamepath:
def __setitem__(self, uid, value):
savehook_new_data[uid]["gamepath"] = value
def __getitem__(self, uid):
return savehook_new_data.get(uid, {}).get("gamepath", None)
uid2gamepath = __uid2gamepath()
def syncconfig(config1, default, drop=False, deep=0, skipdict=False):
@ -367,8 +424,8 @@ def saveallconfig():
safesave("./userconfig/ocrerrorfix.json", ocrerrorfix)
safesave("./userconfig/ocrsetting.json", ocrsetting)
safesave(
"./userconfig/savehook_new_1.39.4.json",
[savehook_new_list, savehook_new_data, savegametaged],
"./userconfig/savegamedata_5.3.1.json",
[savehook_new_list, savehook_new_data, savegametaged, gamepath2uid],
)
safesave(
"./files/lang/{}.json".format(getlanguse()),

View File

@ -10,21 +10,19 @@ from myutils.wrapper import threader
@threader
def grabwindow(app="PNG", callback=None):
if callback:
fnamebase = "cache/temp"
fname = gobject.gettempdir(time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()))
else:
fnamebase = "cache/screenshot/{}".format(0)
dirname = "0"
try:
if gobject.baseobject.textsource.md5 != "0":
fnamebase = "cache/screenshot/{}".format(
gobject.baseobject.textsource.basename
)
dirname = gobject.baseobject.textsource.basename
except:
pass
if os.path.exists(fnamebase) == False:
os.mkdir(fnamebase)
fname = "{}/{}".format(
fnamebase, time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime())
)
fname = gobject.getcachedir(
f"screenshot/{dirname}/"
+ time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()),
)
hwnd = windows.FindWindow(
"Window_Magpie_967EB565-6F73-4E94-AE53-00CC42592A22", None
@ -154,8 +152,9 @@ def getExeIcon(name, icon=True, cache=False):
name = exepath
data = winsharedutils.extracticon2data(name)
if cache:
os.makedirs("./cache/icon", exist_ok=True)
fn = "./cache/icon/{}.bmp".format(hashlib.md5(name.encode("utf8")).hexdigest())
fn = gobject.getcachedir(
"icon/{}.bmp".format(hashlib.md5(name.encode("utf8")).hexdigest())
)
if data:
pixmap = QPixmap()
pixmap.loadFromData(data)

View File

@ -373,22 +373,24 @@ def POSTSOLVE(line):
usemypostpath = "./userconfig/mypost.py"
usemodule = "mypost"
try:
if gobject.baseobject.textsource and ("pname" in dir(gobject.baseobject.textsource)):
exepath = gobject.baseobject.textsource.pname
if not savehook_new_data[exepath]["textproc_follow_default"]:
useranklist = savehook_new_data[exepath]["save_text_process_info"][
if gobject.baseobject.textsource:
gameuid = gobject.baseobject.textsource.gameuid
if gameuid and not savehook_new_data[gameuid]["textproc_follow_default"]:
useranklist = savehook_new_data[gameuid]["save_text_process_info"][
"rank"
]
usedpostprocessconfig = savehook_new_data[exepath][
usedpostprocessconfig = savehook_new_data[gameuid][
"save_text_process_info"
]["postprocessconfig"]
if savehook_new_data[exepath]["save_text_process_info"]["mypost"]:
if savehook_new_data[gameuid]["save_text_process_info"].get(
"mypost", None
):
usemodule = (
"posts."
+ savehook_new_data[exepath]["save_text_process_info"]["mypost"]
+ savehook_new_data[gameuid]["save_text_process_info"]["mypost"]
)
usemypostpath = "./userconfig/posts/{}.py".format(
savehook_new_data[exepath]["save_text_process_info"]["mypost"]
savehook_new_data[gameuid]["save_text_process_info"]["mypost"]
)
except:
print_exc()

View File

@ -3,7 +3,7 @@ import os, time
from traceback import print_exc
import codecs, hashlib
import os, time
import socket, gobject
import socket, gobject, uuid
import ctypes, importlib
import time
import ctypes.wintypes
@ -15,7 +15,8 @@ from myutils.config import (
static_data,
getlanguse,
savehook_new_data,
_TR,
uid2gamepath,
gamepath2uid,
getdefaultsavehook,
)
from ctypes import c_float, pointer, c_void_p
@ -30,14 +31,15 @@ def __internal__getlang(k1, k2):
if not gobject.baseobject.textsource:
break
if "pname" not in dir(gobject.baseobject.textsource):
gameuid = gobject.baseobject.textsource.gameuid
if not gameuid:
break
exepath = gobject.baseobject.textsource.pname
if savehook_new_data[exepath]["lang_follow_default"]:
if savehook_new_data[gameuid]["lang_follow_default"]:
break
return static_data["language_list_translator_inner"][
savehook_new_data[exepath][k1]
savehook_new_data[gameuid][k1]
]
except:
pass
@ -116,16 +118,18 @@ class PriorityQueue:
searchvndbqueue = PriorityQueue()
def guessmaybetitle(gamepath):
def guessmaybetitle(gamepath, title):
__t = []
print(gamepath)
for _ in [
savehook_new_data[gamepath]["title"],
title,
os.path.basename(os.path.dirname(gamepath)),
os.path.basename(gamepath)[:-4],
]:
if not title:
continue
_ = _.replace("(同人ゲーム)", "").replace("(18禁ゲーム)", "")
_ = re.sub(r"\[RJ(.*?)\]", "", _)
_ = re.sub(r"\[\d{4}-?\d{2}\-?\d{2}\]", "", _)
@ -150,7 +154,7 @@ def guessmaybetitle(gamepath):
targetmod = {}
def trysearchforid(gamepath, searchargs: list):
def trysearchforid(gameuid, searchargs: list):
infoid = None
primitivtemetaorigin = globalconfig["primitivtemetaorigin"]
__ = list(targetmod.keys())
@ -168,17 +172,17 @@ def trysearchforid(gamepath, searchargs: list):
if not vid:
continue
idname = globalconfig["metadata"][key]["target"]
savehook_new_data[gamepath][idname] = vid
savehook_new_data[gameuid][idname] = vid
if infoid is None or key == primitivtemetaorigin:
infoid = key, vid
if key == primitivtemetaorigin:
break
if infoid:
searchvndbqueue.put((1, gamepath, infoid))
searchvndbqueue.put((1, gameuid, infoid))
return infoid
def trysearchfordata(gamepath, key, vid):
def trysearchfordata(gameuid, key, vid):
try:
data = targetmod[key].searchfordata(vid)
except:
@ -193,34 +197,34 @@ def trysearchfordata(gamepath, key, vid):
for _ in imagepath_all:
if _ is None:
continue
if _ not in savehook_new_data[gamepath]["imagepath_all"]:
savehook_new_data[gamepath]["imagepath_all"].append(_)
if _ not in savehook_new_data[gameuid]["imagepath_all"]:
savehook_new_data[gameuid]["imagepath_all"].append(_)
if title:
if not savehook_new_data[gamepath]["istitlesetted"]:
savehook_new_data[gamepath]["title"] = title
if not savehook_new_data[gameuid]["istitlesetted"]:
savehook_new_data[gameuid]["title"] = title
_vis = globalconfig["metadata"][key]["name"]
_url = targetmod[key].refmainpage(vid)
_urls = [_[1] for _ in savehook_new_data[gamepath]["relationlinks"]]
_urls = [_[1] for _ in savehook_new_data[gameuid]["relationlinks"]]
if _url not in _urls:
savehook_new_data[gamepath]["relationlinks"].append(
savehook_new_data[gameuid]["relationlinks"].append(
(_vis, targetmod[key].refmainpage(vid))
)
if namemap:
savehook_new_data[gamepath]["namemap"] = namemap
savehook_new_data[gameuid]["namemap"] = namemap
if len(webtags):
savehook_new_data[gamepath]["webtags"] = webtags
savehook_new_data[gameuid]["webtags"] = webtags
if len(developers):
savehook_new_data[gamepath]["developers"] = developers
savehook_new_data[gameuid]["developers"] = developers
return True
def everymethodsthread():
while True:
_ = searchvndbqueue.get()
_type, gamepath, arg = _
_type, gameuid, arg = _
try:
if _type == 0:
infoid = trysearchforid(gamepath, arg)
infoid = trysearchforid(gameuid, arg)
key, vid = infoid
gobject.baseobject.translation_ui.displayglobaltooltip.emit(
f"{key}: found {vid}"
@ -228,7 +232,7 @@ def everymethodsthread():
elif _type == 1:
key, vid = arg
if trysearchfordata(gamepath, key, vid):
if trysearchfordata(gameuid, key, vid):
gobject.baseobject.translation_ui.displayglobaltooltip.emit(
f"{key}: {vid} data loaded"
)
@ -241,8 +245,8 @@ def everymethodsthread():
print_exc()
def gamdidchangedtask(key, idname, gamepath):
vid = savehook_new_data[gamepath][idname]
def gamdidchangedtask(key, idname, gameuid):
vid = savehook_new_data[gameuid][idname]
if vid == "":
return
else:
@ -253,26 +257,34 @@ def gamdidchangedtask(key, idname, gamepath):
except:
print(vid)
return
savehook_new_data[gamepath][idname] = vid
searchvndbqueue.put((1, gamepath, (key, vid)), 1)
savehook_new_data[gameuid][idname] = vid
searchvndbqueue.put((1, gameuid, (key, vid)), 1)
except:
print_exc()
def titlechangedtask(gamepath, title):
savehook_new_data[gamepath]["title"] = title
savehook_new_data[gamepath]["istitlesetted"] = True
searchvndbqueue.put((0, gamepath, [title]), 1)
def titlechangedtask(gameuid, title):
savehook_new_data[gameuid]["title"] = title
savehook_new_data[gameuid]["istitlesetted"] = True
searchvndbqueue.put((0, gameuid, [title]), 1)
def checkifnewgame(targetlist, gamepath, title=None):
isnew = gamepath not in targetlist
if gamepath not in gamepath2uid:
uid = f"{time.time()}_{uuid.uuid4()}"
gamepath2uid[gamepath] = uid
savehook_new_data[uid] = getdefaultsavehook(gamepath, title)
uid2gamepath[uid] = gamepath
searchvndbqueue.put((0, uid, [title] + guessmaybetitle(gamepath, title)))
else:
uid = gamepath2uid[gamepath]
isnew = uid not in targetlist
if isnew:
targetlist.insert(0, gamepath)
if gamepath not in savehook_new_data:
savehook_new_data[gamepath] = getdefaultsavehook(gamepath, title)
searchvndbqueue.put((0, gamepath, [title] + guessmaybetitle(gamepath)))
return isnew
targetlist.insert(0, uid)
return uid
else:
return None
kanjichs2ja = str.maketrans(static_data["kanjichs2ja"])

View File

@ -1,15 +1,12 @@
import requests
from ocrengines.baseocrclass import baseocr
import os, uuid
from myutils.ocrutil import binary2qimage
import os, uuid, gobject
class OCR(baseocr):
def ocr(self, imagebinary):
os.makedirs("cache/temp", exist_ok=True)
fname = "cache/temp/" + str(uuid.uuid4()) + ".png"
fname = gobject.gettempdir(str(uuid.uuid4()) + ".png")
with open(fname, "wb") as ff:
ff.write(imagebinary)
self.checkempty(["Port"])

View File

@ -1,4 +1,4 @@
import os, uuid
import os, uuid, gobject
from myutils.config import _TR, ocrsetting
from ocrengines.baseocrclass import baseocr
from myutils.subproc import subproc_w
@ -24,8 +24,7 @@ class OCR(baseocr):
if os.path.exists(path) == False:
raise Exception(_TR("路径不存在"))
os.makedirs("cache/temp", exist_ok=True)
fname = "cache/temp/" + str(uuid.uuid4()) + ".png"
fname = gobject.gettempdir(str(uuid.uuid4()) + ".png")
with open(fname, "wb") as ff:
ff.write(imagebinary)
imgfile = os.path.abspath(fname)

View File

@ -1,8 +1,8 @@
try:
from PyQt5 import QtSvg
from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox
from PyQt5.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QAction,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect
from PyQt5.QtGui import QIconEngine,QIntValidator,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent
from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl
from PyQt5.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation
isqt5 = True
class LineHeightTypes:
LineDistanceHeight=QTextBlockFormat.LineHeightTypes.LineDistanceHeight
@ -11,9 +11,9 @@ except:
#from traceback import print_exc
#print_exc()
from PyQt6 import QtSvg
from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox
from PyQt6.QtWidgets import QFrame,QListView,QCheckBox,QAbstractItemView,QTextEdit,QTableView,QHeaderView,QColorDialog,QSpinBox,QDoubleSpinBox,QComboBox,QDialogButtonBox,QMainWindow,QMessageBox,QDialog,QGridLayout,QTextBrowser,QGraphicsDropShadowEffect,QWidget,QSizePolicy,QScrollArea,QApplication,QPushButton,QSystemTrayIcon,QPlainTextEdit,QMenu,QFileDialog,QKeySequenceEdit,QLabel,QSpacerItem,QWidgetItem,QLayout,QTextBrowser,QLineEdit,QFormLayout,QSizePolicy,QTabWidget,QTabBar,QSplitter,QListWidget,QListWidgetItem,QHBoxLayout,QVBoxLayout,QSizeGrip,QFontComboBox,QProgressBar,QRadioButton,QButtonGroup,QSlider,QToolTip,QGroupBox,QGraphicsOpacityEffect
from PyQt6.QtGui import QIconEngine,QIntValidator,QAction,QStandardItem,QStandardItemModel,QImageWriter,QIcon,QTextCharFormat,QTextBlockFormat,QResizeEvent,QTextCursor,QFontMetricsF,QMouseEvent,QImage,QPainter,QRegion,QCloseEvent,QFontDatabase,QKeySequence,QPixmap,QCursor,QColor,QFont,QPen,QPainterPath,QBrush,QFontMetrics,QShowEvent,QWheelEvent,QPaintEvent
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl
from PyQt6.QtCore import QObject,pyqtSignal,Qt,QSize,QByteArray,QBuffer,QPointF,QPoint,QRect,QEvent,QModelIndex,QTimer,QRectF,QVariantAnimation,QUrl,QPropertyAnimation
isqt5 = False
class LineHeightTypes:

View File

@ -1,6 +1,6 @@
from scalemethod.base import scalebase
import os, json
import windows
import windows, gobject
from myutils.config import globalconfig, magpie_config
from myutils.subproc import subproc_w
from myutils.wrapper import threader
@ -25,8 +25,7 @@ class Method(scalebase):
def init(self):
self.statuslistener()
os.makedirs("cache/temp", exist_ok=True)
self.jspath = os.path.abspath("cache/temp/magpie.config.json")
self.jspath = gobject.gettempdir("magpie.config.json")
self.engine = subproc_w(
'./files/plugins/Magpie/Magpie.Core.exe "{}"'.format(self.jspath),
cwd="./files/plugins/Magpie/",

View File

@ -10,6 +10,8 @@ from textsource.textsourcebase import basetext
from myutils.utils import checkchaos
from myutils.hwnd import injectdll
from myutils.wrapper import threader
from myutils.utils import getfilemd5
from ctypes import (
CDLL,
CFUNCTYPE,
@ -85,7 +87,7 @@ EmbedCallback = CFUNCTYPE(None, c_wchar_p, ThreadParam)
class texthook(basetext):
@property
def config(self):
if savehook_new_data[self.pname]["hooksetting_follow_default"]:
if savehook_new_data[self.gameuid]["hooksetting_follow_default"]:
return globalconfig
else:
@ -96,22 +98,24 @@ class texthook(basetext):
else:
return globalconfig[key]
return __shitdict(savehook_new_data[self.pname]["hooksetting_private"])
return __shitdict(savehook_new_data[self.gameuid]["hooksetting_private"])
def __init__(
self, pids, hwnd, pname, autostarthookcode=None, needinserthookcode=None
self,
pids,
hwnd,
gamepath,
gameuid,
autostarthookcode=None,
needinserthookcode=None,
):
if autostarthookcode is None:
autostarthookcode = []
if needinserthookcode is None:
needinserthookcode = []
self.pname = pname
self.pids = pids
self.hwnd = hwnd
self.keepref = []
self.newline = Queue()
self.newline_delaywait = Queue()
self.is64bit = Is64bit(pids[0])
self.hookdatacollecter = OrderedDict()
self.hooktypecollecter = OrderedDict()
self.currentname = None
@ -119,30 +123,41 @@ class texthook(basetext):
self.forward = []
self.selectinghook = None
self.selectedhook = []
self.showonce = False
self.selectedhookidx = []
self.allow_set_text_name = self.config["allow_set_text_name"]
self.connectedpids = []
self.runonce_line = ""
self.autostarthookcode = [self.deserial(__) for __ in autostarthookcode]
self.isremoveuseless = self.config["removeuseless"] and len(
self.autostarthookcode
)
self.needinserthookcode = needinserthookcode
self.removedaddress = []
super(texthook, self).__init__(*self.checkmd5prefix(gamepath))
self.gamepath = gamepath
self.gameuid = gameuid
self.pids = pids
self.is64bit = Is64bit(pids[0])
self.hwnd = hwnd
gobject.baseobject.hookselectdialog.changeprocessclearsignal.emit(self.config)
self.allow_set_text_name = self.config["allow_set_text_name"]
self.isremoveuseless = self.config["removeuseless"] and len(
self.autostarthookcode
)
if (
len(autostarthookcode) == 0
and len(savehook_new_data[self.pname]["embedablehook"]) == 0
and len(savehook_new_data[self.gameuid]["embedablehook"]) == 0
):
gobject.baseobject.hookselectdialog.realshowhide.emit(True)
self.delaycollectallselectedoutput()
super(texthook, self).__init__(*self.checkmd5prefix(pname))
self.declare()
self.start()
def checkmd5prefix(self, gamepath):
md5 = getfilemd5(gamepath)
name = os.path.basename(gamepath).replace(
"." + os.path.basename(gamepath).split(".")[-1], ""
)
return md5, name
def declare(self):
LunaHost = CDLL(
@ -254,14 +269,24 @@ class texthook(basetext):
def onprocconnect(self, pid):
self.connectedpids.append(pid)
time.sleep(savehook_new_data[self.pname]["inserthooktimeout"] / 1000)
time.sleep(savehook_new_data[self.gameuid]["inserthooktimeout"] / 1000)
for hookcode in self.needinserthookcode:
self.Luna_InsertHookCode(pid, hookcode)
self.showgamename()
self.flashembedsettings(pid)
def showgamename(self):
if self.showonce:
return
self.showonce = False
gobject.baseobject.textgetmethod(
"<msg_info_refresh>" + savehook_new_data[self.gameuid]["title"]
)
def newhookinsert(self, addr, hcode):
for _hc, _addr, _ctx1, _ctx2 in savehook_new_data[self.pname]["embedablehook"]:
for _hc, _addr, _ctx1, _ctx2 in savehook_new_data[self.gameuid][
"embedablehook"
]:
if hcode == _hc:
self.useembed(addr, _ctx1, _ctx2, True)
@ -339,8 +364,8 @@ class texthook(basetext):
self.hookdatacollecter[key] = []
self.hooktypecollecter[key] = 0
if self.allow_set_text_name:
for jskey in savehook_new_data[self.pname]["hooktypeasname"]:
if savehook_new_data[self.pname]["hooktypeasname"][jskey] == 0:
for jskey in savehook_new_data[self.gameuid]["hooktypeasname"]:
if savehook_new_data[self.gameuid]["hooktypeasname"][jskey] == 0:
continue
if self.match_compatibility(self.deserial(json.loads(jskey)), key):
self.hooktypecollecter[key] = 1
@ -396,7 +421,7 @@ class texthook(basetext):
usestruct.searchTime = 30000
usestruct.maxRecords = 100000
usestruct.codepage = self.codepage()
usestruct.boundaryModule = os.path.basename(self.pname)
usestruct.boundaryModule = os.path.basename(self.gamepath)
usestruct.jittype = 0
return usestruct
@ -462,8 +487,6 @@ class texthook(basetext):
self.newline.put(_collector)
self.runonce_line = _collector
collector.clear()
def handle_output(self, hc, hn, tp, output):

View File

@ -2,28 +2,30 @@ import threading, gobject, queue
import time, sqlite3, json, os
from traceback import print_exc
from myutils.config import globalconfig, savehook_new_data
from myutils.utils import getfilemd5, autosql
from myutils.utils import autosql
class basetext:
def __init__(self, md5, basename):
self.textgetmethod = gobject.baseobject.textgetmethod
self.ending = False
self.sqlqueue = queue.Queue()
if "hwnd" not in dir(self):
self.hwnd = 0
if "pids" not in dir(self):
self.pids = []
self.md5 = md5
self.basename = basename
os.makedirs("./translation_record", exist_ok=True)
sqlfname_all_old = (
"./translation_record/" + md5 + "_" + basename + ".pretrans_common.sqlite"
self.hwnd = None
self.pids = []
self.gameuid = None
#
self.textgetmethod = gobject.baseobject.textgetmethod
self.ending = False
self.sqlqueue = queue.Queue()
sqlfname_all_old = gobject.gettranslationrecorddir(
md5 + "_" + basename + ".pretrans_common.sqlite"
)
sqlfname_all = "./translation_record/" + basename + "_" + md5 + ".sqlite"
sqlfname_all = gobject.gettranslationrecorddir(basename + "_" + md5 + ".sqlite")
if os.path.exists(sqlfname_all_old):
sqlfname_all = sqlfname_all_old
self.uuname = basename + "_" + md5
try:
# self.sqlwrite=sqlite3.connect(self.sqlfname,check_same_thread = False, isolation_level=None)
@ -74,7 +76,7 @@ class basetext:
"SELECT * FROM artificialtrans WHERE source = ?", (src,)
).fetchone()
try:
savehook_new_data[self.pname]["statistic_wordcount"] += lensrc
savehook_new_data[self.gameuid]["statistic_wordcount"] += lensrc
except:
pass
if ret is None:
@ -89,7 +91,7 @@ class basetext:
(src, json.dumps({})),
)
try:
savehook_new_data[self.pname][
savehook_new_data[self.gameuid][
"statistic_wordcount_nodump"
] += lensrc
except:
@ -111,20 +113,6 @@ class basetext:
except:
print_exc()
def checkmd5prefix(self, pname):
md5 = getfilemd5(pname)
name = os.path.basename(pname).replace(
"." + os.path.basename(pname).split(".")[-1], ""
)
return md5, name
def showgamename(self):
if "showonce" not in dir(self):
gobject.baseobject.textgetmethod(
"<msg_info_refresh>" + savehook_new_data[self.pname]["title"]
)
self.showonce = 1
def gettextthread_(self):
while True:
if self.ending:

View File

@ -10,7 +10,7 @@ class TS(basetrans):
return x # {"zh":"ZH","ja":"JA","en":"EN","es":"ES","fr":"FR","ru":"RU"}
def translate(self, query):
self.checkempty(["api"])
payload = {
"text": query,
"source_lang": self.srclang,

View File

@ -109,10 +109,12 @@ class basetrans(commonbase):
if self.transtype != "pre":
try:
os.makedirs("./translation_record/cache", exist_ok=True)
self.sqlwrite2 = autosql(
sqlite3.connect(
"./translation_record/cache/{}.sqlite".format(self.typename),
gobject.gettranslationrecorddir(
"cache/{}.sqlite".format(self.typename)
),
check_same_thread=False,
isolation_level=None,
)

View File

@ -11,8 +11,8 @@ import winsharedutils
class TS(basetrans):
def unsafegetcurrentgameconfig(self):
try:
_path = gobject.baseobject.textsource.pname
_path = savehook_new_data[_path]["gamesqlitefile"]
gameuid = gobject.baseobject.textsource.gameuid
_path = savehook_new_data[gameuid]["gamesqlitefile"]
return _path
except:
return None

View File

@ -24,8 +24,8 @@ class TS(basetrans):
def unsafegetcurrentgameconfig(self):
try:
_path = gobject.baseobject.textsource.pname
_path = savehook_new_data[_path]["gamejsonfile"]
gameuid = gobject.baseobject.textsource.gameuid
_path = savehook_new_data[gameuid]["gamejsonfile"]
if isinstance(_path, str):
_path = [_path]
return tuple(_path)

View File

@ -6,8 +6,8 @@ class Process:
def process_before(self, s):
exepath = gobject.baseobject.textsource.pname
namemap = savehook_new_data[exepath]["namemap"]
gameuid = gobject.baseobject.textsource.gameuid
namemap = savehook_new_data[gameuid]["namemap"]
bettermap = {}
for k, v in namemap.items():
for sp in ["", " "]:

View File

@ -2,7 +2,7 @@ import time
import os
import windows
from tts.basettsclass import TTSbase
import ctypes, subprocess
import ctypes, subprocess, gobject
from myutils.subproc import subproc_w, autoproc
from ctypes import cast, POINTER, c_char, c_int32
@ -69,8 +69,7 @@ class TTS(TTSbase):
return self.mapx[(hk, idx)]
def getvoicelist(self):
os.makedirs("cache/temp", exist_ok=True)
cachefname = os.path.abspath("cache/temp/{}.txt".format(time.time()))
cachefname = gobject.gettempdir(f"{time.time()}.txt")
exe = os.path.abspath("./files/plugins/shareddllproxy32.exe")
subprocess.run('"{}" neospeechlist "{}"'.format(exe, cachefname))

View File

@ -6,7 +6,7 @@
},
"DeepLX": {
"args": {
"api": "https://api.deeplx.org/translate"
"api": ""
}
},
"baiduapi": {

View File

@ -29,7 +29,7 @@ include(generate_product_version)
set(VERSION_MAJOR 5)
set(VERSION_MINOR 3)
set(VERSION_PATCH 0)
set(VERSION_PATCH 1)
add_library(pch pch.cpp)
target_precompile_headers(pch PUBLIC pch.h)