diff --git a/LunaTranslator/LunaTranslator/gui/setting_translate.py b/LunaTranslator/LunaTranslator/gui/setting_translate.py index a090f351..f977ee49 100644 --- a/LunaTranslator/LunaTranslator/gui/setting_translate.py +++ b/LunaTranslator/LunaTranslator/gui/setting_translate.py @@ -24,6 +24,7 @@ from gui.usefulwidget import ( makescrollgrid, getvboxwidget, ) +from traceback import print_exc from gui.dynalang import LPushButton, LLabel @@ -62,6 +63,8 @@ def loadvisinternal(btnplus, copy): is_gpt_likes, not_is_gpt_like = splitapillm(shoufei) elif btnplus == "offline": is_gpt_likes, not_is_gpt_like = splitapillm(lixians) + elif btnplus == "develop": + is_gpt_likes, not_is_gpt_like = splitapillm(develop) for _ in is_gpt_likes: if copy: @@ -268,11 +271,21 @@ def createmanybtn(self, countnum, btnplus): btn.setIcon(qtawesome.icon("fa.question")) if btnplus == "offline": btn.clicked.connect( - lambda: gobject.baseobject.openlink(dynamiclink("{docs_server}/#/zh/offlinellm")) + lambda: gobject.baseobject.openlink( + dynamiclink("{docs_server}/#/zh/offlinellm") + ) ) elif btnplus == "api": btn.clicked.connect( - lambda: gobject.baseobject.openlink(dynamiclink("{docs_server}/#/zh/guochandamoxing")) + lambda: gobject.baseobject.openlink( + dynamiclink("{docs_server}/#/zh/guochandamoxing") + ) + ) + elif btnplus == "develop": + btn.clicked.connect( + lambda: gobject.baseobject.openlink( + dynamiclink("{docs_server}/#/zh/tiaoshiliulanqi") + ) ) hbox.addWidget(btn) setattr(self, "btnmany" + btnplus, w) @@ -506,7 +519,7 @@ def setTabTwo_lazy(self, basel): offlinegrid = initsome2(self, lixians, btnplus="offline") onlinegrid = initsome11(self, mianfei) - developgrid += initsome2(self, develop) + developgrid += initsome2(self, develop, btnplus="develop") online_reg_grid += initsome2(self, shoufei, btnplus="api") pretransgrid += initsome11(self, pre) vw, vl = getvboxwidget() diff --git a/LunaTranslator/LunaTranslator/translator/commonhookfetchstream.js b/LunaTranslator/LunaTranslator/translator/commonhookfetchstream.js index 501b56d3..e4f59aa8 100644 --- a/LunaTranslator/LunaTranslator/translator/commonhookfetchstream.js +++ b/LunaTranslator/LunaTranslator/translator/commonhookfetchstream.js @@ -4,7 +4,7 @@ if (window.injectedjs) return window.injectedjs = true const originalFetch = window.fetch; - window.fetch = function (input, init) { + window.fetch = function (url, init) { const fetchPromise = originalFetch.apply(this, arguments); if (!%s) return fetchPromise; window.hasdone = false; @@ -27,8 +27,13 @@ let line = lines[i] line = line.trim() if (line.length == 0) continue; + if (line.substring(6) == '[DONE]') { + hasdone = true; + break; + } try { - %s + const chunk = JSON.parse(line.substring(6)); + %s } catch { } diff --git a/LunaTranslator/LunaTranslator/translator/commonhookxhrstream.js b/LunaTranslator/LunaTranslator/translator/commonhookxhrstream.js index 6d3b1380..bfa59f26 100644 --- a/LunaTranslator/LunaTranslator/translator/commonhookxhrstream.js +++ b/LunaTranslator/LunaTranslator/translator/commonhookxhrstream.js @@ -3,13 +3,13 @@ window.thistext = '' if (window.injectedjs) return window.injectedjs = true - const originXHR = XMLHttpRequest + const originXHR = XMLHttpRequest window.XMLHttpRequest = function () { var newxhr = new originXHR() newxhr.open_ori = newxhr.open newxhr.open = function () { - var input = arguments[1] + var url = arguments[1] if (%s) { window.hasdone = false; window.thistext = '' @@ -29,8 +29,13 @@ let line = lines[i] line = line.trim() if (line.length == 0) continue; + if (line.substring(6) == '[DONE]') { + hasdone = true; + break; + } try { - %s + const chunk = JSON.parse(line.substring(6)); + %s } catch { } diff --git a/LunaTranslator/LunaTranslator/translator/dev_chatglm.py b/LunaTranslator/LunaTranslator/translator/dev_chatglm.py index a62d948a..20fe33d0 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_chatglm.py +++ b/LunaTranslator/LunaTranslator/translator/dev_chatglm.py @@ -4,16 +4,7 @@ from translator.dev_llm_common import commonllmdev class TS(commonllmdev): target_url = "https://chatglm.cn/main/alltoolsdetail" jsfile = "commonhookfetchstream.js" - function1 = 'input.endsWith("assistant/stream")' - function2 = """const chunk = JSON.parse(line.substring(6)); - thistext = chunk.parts[0].content[0].text""" - - def dotranslate(self, content): - self.Runtime_evaluate( - 'document.querySelector("#search-input-box > div.input-wrap.flex.flex-x-between.flex-y-center > div.input-box-inner > textarea").focus()' - ) - self.send_keys(content) - - self.Runtime_evaluate( - """document.querySelector("#search-input-box > div.input-wrap.flex.flex-x-between.flex-y-center > div.enter.m-three-row > img").click()""" - ) + function1 = 'url.endsWith("assistant/stream")' + function2 = """thistext = chunk.parts[0].content[0].text""" + textarea_selector = "#search-input-box > div.input-wrap.flex.flex-x-between.flex-y-center > div.input-box-inner > textarea" + button_selector = "#search-input-box > div.input-wrap.flex.flex-x-between.flex-y-center > div.enter.m-three-row > img" diff --git a/LunaTranslator/LunaTranslator/translator/dev_chatgpt.py b/LunaTranslator/LunaTranslator/translator/dev_chatgpt.py index 156ba7c9..907c3b43 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_chatgpt.py +++ b/LunaTranslator/LunaTranslator/translator/dev_chatgpt.py @@ -4,16 +4,7 @@ from translator.dev_llm_common import commonllmdev class TS(commonllmdev): target_url = "https://chatgpt.com/" jsfile = "commonhookfetchstream.js" - function1 = 'input.includes("conversation")' - function2 = r"""const chunk = JSON.parse(line.substring(6)); - thistext = chunk.message.content.parts[0]""" - - def dotranslate(self, content): - self.Runtime_evaluate( - 'textarea=document.querySelector("#prompt-textarea");textarea.value="";event = new Event("input", {{bubbles: true, cancelable: true }});textarea.dispatchEvent(event);textarea.value=`{}`;event = new Event("input", {{bubbles: true, cancelable: true }});textarea.dispatchEvent(event);'.format( - content - ) - ) - self.Runtime_evaluate( - r"""document.querySelector("#__next > div.relative.z-0.flex.h-full.w-full.overflow-hidden > div > main > div.flex.h-full.flex-col.focus-visible\\:outline-0 > div.md\\:pt-0.dark\\:border-white\\/20.md\\:border-transparent.md\\:dark\\:border-transparent.w-full > div.text-base.px-3.md\\:px-4.m-auto.md\\:px-5.lg\\:px-1.xl\\:px-5 > div > form > div > div.flex.w-full.items-center > div > div > button").click()""" - ) + function1 = 'url.includes("conversation")' + function2 = r"""thistext = chunk.message.content.parts[0]""" + textarea_selector = "#prompt-textarea" + button_selector = r"#__next > div.relative.z-0.flex.h-full.w-full.overflow-hidden > div > main > div.flex.h-full.flex-col.focus-visible\\:outline-0 > div.md\\:pt-0.dark\\:border-white\\/20.md\\:border-transparent.md\\:dark\\:border-transparent.w-full > div.text-base.px-3.md\\:px-4.m-auto.md\\:px-5.lg\\:px-1.xl\\:px-5 > div > form > div > div.flex.w-full.items-center > div > div > button" diff --git a/LunaTranslator/LunaTranslator/translator/dev_chatgpt_mirror.py b/LunaTranslator/LunaTranslator/translator/dev_chatgpt_mirror.py new file mode 100644 index 00000000..d1a5a245 --- /dev/null +++ b/LunaTranslator/LunaTranslator/translator/dev_chatgpt_mirror.py @@ -0,0 +1,30 @@ +from translator.dev_llm_common import commonllmdev + + +class TS(commonllmdev): + + @property + def target_url(self): + return self.config["target_url"] + + @property + def jsfile(self): + return ["commonhookfetchstream.js", "commonhookxhrstream"][ + self.config["request_method"] + ] + + @property + def function1(self): + return self.config["checkneturlfunction"] + + @property + def function2(self): + return self.config["extracttextfunction"] + + @property + def button_selector(self): + return self.config["button_selector"] + + @property + def textarea_selector(self): + return self.config["textarea_selector"] diff --git a/LunaTranslator/LunaTranslator/translator/dev_deepseek.py b/LunaTranslator/LunaTranslator/translator/dev_deepseek.py index af5d3a80..934b8b87 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_deepseek.py +++ b/LunaTranslator/LunaTranslator/translator/dev_deepseek.py @@ -4,12 +4,9 @@ from translator.dev_llm_common import commonllmdev class TS(commonllmdev): target_url = "https://chat.deepseek.com/" jsfile = "commonhookxhrstream.js" - function1 = "input.endsWith('v0/chat/completions')" - function2 = r"""const chunk = JSON.parse(line.substring(6)); - if(!!(chunk.choices[0].delta.content)) + function1 = "url.endsWith('v0/chat/completions')" + function2 = r"""if(!!(chunk.choices[0].delta.content)) thistext += chunk.choices[0].delta.content""" - def dotranslate(self, content): - self.Runtime_evaluate('document.querySelector("#chat-input").click()') - self.send_keys(content) - self.Runtime_evaluate("document.getElementsByClassName('_89d4d19')[1].click()") + textarea_selector = "#chat-input" + button_selector = "._89d4d19:nth-child(3)" diff --git a/LunaTranslator/LunaTranslator/translator/dev_llm_common.py b/LunaTranslator/LunaTranslator/translator/dev_llm_common.py index fbd34e5f..9ec8631f 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_llm_common.py +++ b/LunaTranslator/LunaTranslator/translator/dev_llm_common.py @@ -3,6 +3,12 @@ import time, os class commonllmdev(basetransdev): + jsfile = ... + textarea_selector = ... + button_selector = ... + function1 = ... + function2 = ... + def langmap(self): return { "zh": "Simplified Chinese", @@ -46,7 +52,26 @@ class commonllmdev(basetransdev): self.srclang, self.tgtlang ) content = prompt + content - self.dotranslate(content) + self.Runtime_evaluate( + f"document.querySelector(`{self.textarea_selector}`).foucs()" + ) + self.send_keys(content) + # chatgpt网站没有焦点时,用这个也可以。 + self.Runtime_evaluate( + f'textarea=document.querySelector(`{self.textarea_selector}`);textarea.value="";event = new Event("input", {{bubbles: true, cancelable: true }});textarea.dispatchEvent(event);textarea.value=`{content}`;event = new Event("input", {{bubbles: true, cancelable: true }});textarea.dispatchEvent(event);' + ) + + try: + # 月之暗面 + while self.Runtime_evaluate( + f"document.querySelector(`{self.button_selector}`).disabled" + )["result"]["value"]: + time.sleep(0.1) + except: + pass + self.Runtime_evaluate( + f"document.querySelector(`{self.button_selector}`).click()" + ) if self.config["usingstream"]: curr = "" while not self.Runtime_evaluate("hasdone")["result"]["value"]: diff --git a/LunaTranslator/LunaTranslator/translator/dev_moonshot.py b/LunaTranslator/LunaTranslator/translator/dev_moonshot.py index a2e9195c..833e2788 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_moonshot.py +++ b/LunaTranslator/LunaTranslator/translator/dev_moonshot.py @@ -4,16 +4,9 @@ from translator.dev_llm_common import commonllmdev class TS(commonllmdev): target_url = "https://kimi.moonshot.cn/" jsfile = "commonhookfetchstream.js" - function1 = 'input.endsWith("completion/stream")' - function2 = """const chunk = JSON.parse(line.substring(6)); - if(chunk.event!='cmpl')continue; + function1 = 'url.endsWith("completion/stream")' + function2 = """if(chunk.event!='cmpl')continue; if(chunk.text) thistext += chunk.text""" - - def dotranslate(self, content): - self.Runtime_evaluate( - 'document.querySelector("#root > div.MuiBox-root.css-qmryj6 > div > div.layoutContent___NvxZ_ > div.MuiBox-root.css-ar9pyi > div > div > div > div.MuiBox-root.css-8atqhb > div.chatInput___bMC0h.matchHomePageLayout___WewPT > div > div > div.editor___KShcc.editor___DSPKC.matchHomePageLayout___XTlpC > div")? document.querySelector("#root > div.MuiBox-root.css-qmryj6 > div > div.layoutContent___NvxZ_ > div.MuiBox-root.css-ar9pyi > div > div > div > div.MuiBox-root.css-8atqhb > div.chatInput___bMC0h.matchHomePageLayout___WewPT > div > div > div.editor___KShcc.editor___DSPKC.matchHomePageLayout___XTlpC > div").click() : document.querySelector("#root > div.MuiBox-root.css-qmryj6 > div > div.layoutContent___NvxZ_ > div.MuiBox-root.css-ar9pyi > div > div > div > div > div.chatPageLayoutRightBoxLeft___taL5l > div.content___inD6V > div > div.chatBottom___jS9Jd.MuiBox-root.css-jdjpte > div.chatInput___bMC0h.matchHomePageLayout___WewPT > div > div > div.editor___KShcc.editor___DSPKC.matchHomePageLayout___XTlpC > div.editorContentEditable___FZJd9").click()' - ) - self.send_keys(content) - self.wait_for_result('document.querySelector("#send-button").disabled', True) - self.Runtime_evaluate("""document.querySelector("#send-button").click()""") + button_selector='#send-button' + textarea_selector='#root > div > div.mainContent___vvQdb > div.layoutContent___NvxZ_ > div.MuiBox-root.css-ar9pyi > div > div > div > div > div.chatPageLayoutRightBoxLeft___taL5l > div.content___inD6V > div > div.chatBottomContainer___MmYFg.MuiBox-root.css-0 > div > div.chatInput___bMC0h > div > div > div.editor___KShcc.editor___DSPKC > div.editorContentEditable___FZJd9' \ No newline at end of file diff --git a/LunaTranslator/LunaTranslator/translator/dev_qwen.py b/LunaTranslator/LunaTranslator/translator/dev_qwen.py index 70073374..2e6bb315 100644 --- a/LunaTranslator/LunaTranslator/translator/dev_qwen.py +++ b/LunaTranslator/LunaTranslator/translator/dev_qwen.py @@ -4,13 +4,8 @@ from translator.dev_llm_common import commonllmdev class TS(commonllmdev): target_url = "https://tongyi.aliyun.com/qianwen" jsfile = "commonhookfetchstream.js" - function1 = 'input.endsWith("dialog/conversation")' - function2 = r"""const chunk = JSON.parse(line.substring(6)); - thistext = chunk.contents[0].content""" - - def dotranslate(self, content): - self.Runtime_evaluate('document.getElementsByTagName("textarea")[0].focus()') - self.send_keys(content) - self.Runtime_evaluate( - r"""document.querySelector("#tongyiPageLayout > div.sc-fQpRED.jsoEZg > div > div.sc-hNGPaV.erDcgy.pageContentWrap--AovzQ5wq > div > div.inputField--PE5FhWzd > div > div.chatInput--eJzBH8LP > div.operateBtn--zFx6rSR0").click()""" - ) + function1 = 'url.endsWith("dialog/conversation")' + function2 = r"""thistext = chunk.contents[0].content""" + textarea_selector = "textarea:first-of-type" + button_selector = ".operateBtn--zFx6rSR0" + # 必须主动给文本框焦点 diff --git a/LunaTranslator/files/defaultconfig/config.json b/LunaTranslator/files/defaultconfig/config.json index b20a76e2..ba276ff4 100644 --- a/LunaTranslator/files/defaultconfig/config.json +++ b/LunaTranslator/files/defaultconfig/config.json @@ -1607,6 +1607,13 @@ "name": "deepseek", "is_gpt_like": true }, + "dev_chatgpt_mirror": { + "use": false, + "color": "blue", + "type": "dev", + "name": "chatgpt mirror", + "is_gpt_like": true + }, "deepl_dev": { "use": false, "color": "blue", diff --git a/LunaTranslator/files/defaultconfig/translatorsetting.json b/LunaTranslator/files/defaultconfig/translatorsetting.json index 0aaf5d1b..d1e8f105 100644 --- a/LunaTranslator/files/defaultconfig/translatorsetting.json +++ b/LunaTranslator/files/defaultconfig/translatorsetting.json @@ -824,7 +824,65 @@ "type": "switch" }, "custom_prompt": { - "name": "自定义_system promt", + "name": "自定义_promt", + "type": "multiline", + "refswitch": "use_custom_prompt" + } + } + }, + "dev_chatgpt_mirror": { + "args": { + "target_url": "https://chatgpt.com/", + "request_method": 0, + "checkneturlfunction": "url.includes(\"conversation\")", + "extracttextfunction": "thistext = chunk.message.content.parts[0]", + "textarea_selector": "#prompt-textarea", + "button_selector": "#__next > div.relative.z-0.flex.h-full.w-full.overflow-hidden > div.relative.flex.h-full.max-w-full.flex-1.flex-col.overflow-hidden > main > div.flex.h-full.flex-col.focus-visible\\\\:outline-0 > div.md\\\\:pt-0.dark\\\\:border-white\\\\/20.md\\\\:border-transparent.md\\\\:dark\\\\:border-transparent.w-full > div.text-base.px-3.md\\\\:px-4.m-auto.md\\\\:px-5.lg\\\\:px-1.xl\\\\:px-5 > div > form > div > div.flex.w-full.items-center > div > div > button", + "S": "", + "usingstream": true, + "use_custom_prompt": false, + "custom_prompt": "" + }, + "argstype": { + "target_url": { + "rank": -10 + }, + "S": { + "rank": 0, + "type": "split" + }, + "textarea_selector": { + "rank": -6, + "name": "CSS selector for textarea" + }, + "button_selector": { + "rank": -5, + "name": "CSS selector for button" + }, + "extracttextfunction": { + "rank": -7, + "name": "Function2 (extract text in stream chunk)" + }, + "checkneturlfunction": { + "rank": -8, + "name": "Function1 (check if url is backend url)" + }, + "request_method": { + "rank": -9, + "type": "combo", + "list": [ + "fetch", + "xhr" + ] + }, + "usingstream": { + "rank": 1, + "name": "流式输出", + "type": "switch" + }, + "custom_prompt": { + "rank": 2, + "name": "自定义_promt", "type": "multiline", "refswitch": "use_custom_prompt" } @@ -842,7 +900,7 @@ "type": "switch" }, "custom_prompt": { - "name": "自定义_system promt", + "name": "自定义_promt", "type": "multiline", "refswitch": "use_custom_prompt" } @@ -860,7 +918,7 @@ "type": "switch" }, "custom_prompt": { - "name": "自定义_system promt", + "name": "自定义_promt", "type": "multiline", "refswitch": "use_custom_prompt" } @@ -878,7 +936,7 @@ "type": "switch" }, "custom_prompt": { - "name": "自定义_system promt", + "name": "自定义_promt", "type": "multiline", "refswitch": "use_custom_prompt" } @@ -896,7 +954,7 @@ "type": "switch" }, "custom_prompt": { - "name": "自定义_system promt", + "name": "自定义_promt", "type": "multiline", "refswitch": "use_custom_prompt" } @@ -1213,7 +1271,7 @@ } } }, - "chatmiko":{ + "chatmiko": { "args": { "model": "deepseek-chat", "附带上下文个数": 0, diff --git a/plugins/CMakeLists.txt b/plugins/CMakeLists.txt index 80142090..46c7eda0 100644 --- a/plugins/CMakeLists.txt +++ b/plugins/CMakeLists.txt @@ -29,7 +29,7 @@ include(generate_product_version) set(VERSION_MAJOR 5) set(VERSION_MINOR 23) -set(VERSION_PATCH 4) +set(VERSION_PATCH 5) add_library(pch pch.cpp) target_precompile_headers(pch PUBLIC pch.h)