您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Zotero GPT Pro, support ChatGPT Gemini Poe Kimi
当前为
// ==UserScript== // @name Zotero GPT Connector // @namespace http://tampermonkey.net/ // @version 1.2 // @description Zotero GPT Pro, support ChatGPT Gemini Poe Kimi // @author Polygon // @match https://chat.openai.com/* // @match https://gemini.google.com/app/* // @match https://poe.com/* // @match https://kimi.moonshot.cn/* // @icon https://cdn.oaistatic.com/_next/static/media/favicon-32x32.be48395e.png // @grant GM_xmlhttpRequest // @grant GM_registerMenuCommand // @grant unsafeWindow // @run-at document-start // ==/UserScript== (async function () { 'use strict'; let AI = "" if (location.host == 'chat.openai.com') { AI = "ChatGPT" } else if (location.host == 'gemini.google.com') { AI = "Gemini" } else if (location.host == 'poe.com') { AI = "Poe" } else if (location.host == 'kimi.moonshot.cn') { AI = "Kimi" } // 在Zotero中执行代码 async function execInZotero(code) { return new Promise((resolve, reject) => { GM_xmlhttpRequest({ method: "POST", url: "http://127.0.0.1:23119/zoterogpt", headers: { "Content-Type": "application/json", }, responseType: "json", data: JSON.stringify({ code }), onload: function (response) { if (response.status >= 200 && response.status < 300) { resolve(response.response.result); } else { reject(new Error(`Request failed with status: ${response.status}`)); } }, onerror: function (error) { reject(new Error('Network error')); } }); }); } // 设定ChatGPT输入框文本并发送 const setText = (text) => { if (AI == "ChatGPT") { // 获取 input 输入框的dom对象 var element_input = window.document.querySelector('#prompt-textarea'); // 修改input的值 element_input.value = text; // 设置输入框的 input 事件 var event = new InputEvent('input', { 'bubbles': true, 'cancelable': true, }); element_input.dispatchEvent(event); document.querySelector("[data-testid=send-button]").click() setTimeout(() => { document.querySelector("[data-testid=send-button]").click() }, 100) } else if (AI == "Gemini") { // 获取 input 输入框的dom对象 var element_input = window.document.querySelector('rich-textarea .textarea'); // 修改input的值 element_input.textContent = text; document.querySelector(".send-button").click(); setTimeout(() => { document.querySelector(".send-button").click() }, 100) } else if (AI == "Poe") { var element_input = window.document.querySelector('textarea[class*=GrowingTextArea_textArea]'); element_input.value = text; // 设置输入框的 input 事件 var event = new InputEvent('input', { 'bubbles': true, 'cancelable': true, }); element_input.dispatchEvent(event); document.querySelector("button[class*=ChatMessageSendButton_sendButton]").click(); setTimeout(() => { document.querySelector("button[class*=ChatMessageSendButton_sendButton]").click() }, 100) } else if (AI == "Kimi") { fetch(`https://kimi.moonshot.cn/api/chat/${location.href.match(/chat\/([0-9a-z]+)/)[1]}/completion/stream`, { method: 'POST', headers: { 'Content-Type': 'application/json', "Authorization": `Bearer ${localStorage.access_token}` }, body: JSON.stringify({ "messages": [{ "role": "user", "content": text }], "refs": [], "use_search": false }) }) .then(response => { let text = "" const reader = response.body.getReader(); const decoder = new TextDecoder(); return reader.read().then(function processText({ done, value }) { if (done) { window.toZotero.isDone = true return; } text += JSON.parse(decoder.decode(value, { stream: true }).split("data: ")[1]).text || "" window.toZotero = { isDone: false, text: text.replace("```markdown", "```\n") } return reader.read().then(processText); }); }) .catch(e => { window.toZotero = { isDone: false, text: "请等待" } location.reload(); sleep(3000) setText(text) }) } } // 阻塞 function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } let isRunning = true GM_registerMenuCommand('🔗 运行', () => { isRunning = true window.alert("🔗 已运行") }); GM_registerMenuCommand('🎊 断开', () => { isRunning = false window.alert("🎊 断开") }); // Ctrl+Enter 发送到Zotero GPT执行 // const callback = async (e) => { // e.stopPropagation(); // e.preventDefault(); // const text = document.querySelector('#prompt-textarea').value // document.querySelector('#prompt-textarea').innerHTML = "Thinking..." // document.querySelector('#prompt-textarea').value = "Thinking..." // console.log("接收文本", JSON.stringify(text)) // await execInZotero(` // const views = Zotero.ZoteroGPT.views; // views.inputContainer.querySelector("input").value = ${JSON.stringify(text)} // window.setTimeout(async()=>{ // await Zotero.ZoteroGPT.views.execText(${JSON.stringify(text) // }) // }) // `) // } // window.setInterval(() => { // const isListener = document.querySelector('#prompt-textarea').getAttribute("is-listener") // if (!isListener) { // document.querySelector('#prompt-textarea') // .addEventListener("keydown", async (e) => { // if (!(e.ctrlKey && e.key == "Enter" && isRunning)) { return } // callback(e) // }) // document.querySelector('#prompt-textarea').setAttribute("is-listener", "1") // } // }, 1000) // 通信 while (true) { if (!isRunning) { await execInZotero(` window.Meet.tasks = undefined `) await sleep(1000) continue; } try { const result = await execInZotero(` if (!window.Meet.tasks){ window.Meet.tasks = [] } else { window.Meet.tasks } `) const tasks = result; if (!tasks || tasks.length == 0) { await sleep(500) continue } const task = tasks.slice(-1)[0] if (task.type == "pending") { if (task.requestText) { // 操作浏览器提问 if (AI == "ChatGPT") { let getUserQuestionNum = () => document.querySelectorAll("[data-message-author-role=user]").length const questionNum = getUserQuestionNum() setText(task.requestText) while (getUserQuestionNum() == questionNum) { await sleep(100) } } else if (AI == "Gemini") { let getUserQuestionNum = () => document.querySelectorAll("user-query").length const questionNum = getUserQuestionNum() setText(task.requestText) while (getUserQuestionNum() == questionNum) { await sleep(100) } while (document.querySelectorAll('model-response').length != getUserQuestionNum()) { await sleep(100) } } else if (AI == "Poe") { let getUserQuestionNum = () => document.querySelectorAll("[class*=ChatMessage_humanMessageWrapper]").length const questionNum = getUserQuestionNum() setText(task.requestText) while (getUserQuestionNum() == questionNum) { await sleep(100) } while (document.querySelectorAll('[class*=Message_botMessageBubble]').length != getUserQuestionNum()) { await sleep(100) } } else if (AI == "Kimi") { setText(task.requestText) } await execInZotero(` let task = window.Meet.tasks[window.Meet.tasks.length-1] task.requestText = ""; task.responseText = "<p>Answering (本过程不消耗Api Key额度)...</p>"; `) } else { let isDone = false, text = "", type = "html" if (AI == "ChatGPT") { const outputEle = [...document.querySelectorAll('[data-testid^=conversation-turn]')].slice(-1)[0]; const contentEle = outputEle.querySelector("div>div>div:nth-child(2)>div:nth-child(2)>div") isDone = Boolean(outputEle.querySelector("div>div>div:nth-child(2)>div:nth-child(2)>div:nth-child(2) button")) text = contentEle.querySelector(".markdown").innerHTML } else if (AI == "Gemini") { const outputEle = [...document.querySelectorAll('model-response')].slice(-1)[0]; const contentEle = outputEle.querySelector(".response-content message-content") isDone = Boolean(outputEle.querySelector(".complete")) text = contentEle.querySelector(".markdown").innerHTML } else if (AI == "Poe") { const outputEle = [...document.querySelectorAll('[class*=Message_botMessageBubble]')].slice(-1)[0]; const contentEle = outputEle.querySelector("[class*=Markdown_markdownContainer]") isDone = Boolean(document.querySelector("[class*=ChatMessageActionBar_actionBar]")) text = contentEle.innerHTML } else if (AI == "Kimi") { isDone = window.toZotero && window.toZotero.isDone text = window.toZotero && window.toZotero.text type = "markdown" } console.log(text) await execInZotero(` let task = window.Meet.tasks[window.Meet.tasks.length-1] task.responseText = ${JSON.stringify(text)}; task.type = ${isDone} ? "done" : "pending"; task.responseType = "${type}" `) if (isDone) { await sleep(1000) await execInZotero(` let task = window.Meet.tasks[window.Meet.tasks.length-1] task.responseText = ${JSON.stringify(text)}; `) } } } } catch (e) { console.log(e) } await sleep(10) } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址