您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Connector
当前为
// ==UserScript== // @name Zotero GPT Connector // @namespace http://tampermonkey.net/ // @version 0.5 // @description Connector // @author Polygon // @match https://chat.openai.com/* // @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'; // 在Zotero中执行代码 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) => { // 获取 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) } // 阻塞 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 == "request") { // 操作浏览器提问 let getUserQuestionNum = () => document.querySelectorAll("[data-message-author-role=user]").length const questionNum = getUserQuestionNum() console.log(task.text) setText(task.text) while (getUserQuestionNum() == questionNum) { await sleep(100) } await execInZotero(` window.Meet.tasks.push({ type: "response", text: "" }) const views = Zotero.ZoteroGPT.views; views.setText("Thinking...", false, true, "text") `) } else if (task.type == "response") { 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") const isDone = Boolean(outputEle.querySelector("div>div>div:nth-child(2)>div:nth-child(2)>div:nth-child(2) button")) const text = contentEle.querySelector(".markdown").innerHTML const taskJson = JSON.stringify({ type: "response", text, isDone }) console.log(taskJson) execInZotero(` let task = window.Meet.tasks[window.Meet.tasks.length-1] if (task.type == "response" && !task.isSetDone) { task = (window.Meet.tasks[window.Meet.tasks.length-1] = ${taskJson}) const views = Zotero.ZoteroGPT.views; views.setText(task.text, task.isDone, true, "html") if (task.isDone) { task.isSetDone = true } } `) } } catch (e) { // console.log(e) } await sleep(10) } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址