- // ==UserScript==
- // @name Zotero GPT Connector
- // @namespace http://tampermonkey.net/
- // @version 2.6.3
- // @description Zotero GPT Pro, support ChatGPT Gemini Poe Kimi Coze Chatglm yiyan
- // @author Polygon
- // @match https://chatgpt.com/*
- // @match https://gemini.google.com/app*
- // @match https://poe.com/*
- // @match https://www.coze.com/*
- // @match https://kimi.moonshot.cn/*
- // @match https://chatglm.cn/*
- // @match https://chatglm.cn/*
- // @match https://yiyan.baidu.com*
- // @match https://tongyi.aliyun.com/qianwen/*
- // @icon https://cdn.oaistatic.com/_next/static/media/favicon-32x32.be48395e.png
- // @grant GM_xmlhttpRequest
- // @grant GM_registerMenuCommand
- // @grant GM_cookie
- // @grant unsafeWindow
- // @run-at document-start
- // ==/UserScript==
-
- (async function () {
- 'use strict';
- let isRunning = true
- let AI = ""
- if (location.host == 'chatgpt.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"
- } else if (location.host == 'www.coze.com') {
- AI = "Coze"
- } else if (location.host == "chatglm.cn") {
- AI = "Chatglm"
- GM_cookie.list({
- url: 'https://chatglm.cn/chatglm/feed-api/assistant_top/v4/recent_list' }, function (cookies, error) {
- if (!error) {
- localStorage.setItem("token", cookies.find(i => i.name == "chatglm_token").value);
- localStorage.conversation_id = ""
- }
- });
- } else if (location.host == 'yiyan.baidu.com') {
- AI = "Yiyan"
- } else if (location.host == 'tongyi.aliyun.com') {
- AI = "Tongyi"
- }
- // 在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) => {
- const originalText = 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);
- const buttons = document.querySelector("#prompt-textarea").parentElement.parentElement.querySelectorAll("button");
- const button = buttons[buttons.length - 1]
- button.click()
- setTimeout(() => {
- 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 => {
- if (response.status == 200) {
- return response.body.getReader()
- } else {
- throw Error("授权失败")
- }
- })
- .then(reader => {
- let text = ""
- const decoder = new TextDecoder();
- window.setTimeout(async () => {
- while (true) {
- const { done, value } = await reader.read();
- if (done) {
- await execInZotero(`
- let task = window.Meet.tasks[window.Meet.tasks.length-1]
- task.responseText = ${JSON.stringify(text)};
- task.type = "done";
- task.responseType = "markdown"
- `)
- break
- }
- try {
- const newLines = decoder.decode(value, { stream: true })
- for (let line of newLines.match(/data: .+/g)) {
- try {
- const data = JSON.parse(line.split("data: ")[1])
- if (data.event && data.event == "cmpl") {
- text += data.text
- } else if (data.error) {
- text += data.error.message;
- console.log(data);
- document.querySelector("[data-testid=msh-sidebar-new]").click();
- window.setTimeout(() => {
- setText(originalText)
- }, 1000)
- return
- }
- } catch { }
- execInZotero(`
- let task = window.Meet.tasks[window.Meet.tasks.length-1]
- task.responseText = ${JSON.stringify(text)};
- task.type = "pending";
- task.responseType = "markdown"
- `)
- }
- } catch (e) {
- console.log(e)
- }
-
- }
- }, 0)
- })
- .catch(e => {
- console.log(e)
-
- window.setTimeout(async () => {
- const res = await fetch("https://kimi.moonshot.cn/api/auth/token/refresh", {
- headers: {
- "Authorization": `Bearer ${localStorage.refresh_token}`
- }
- })
- const data = await res.json()
- localStorage.access_token = data.access_token
- localStorage.refresh_token = data.refresh_token
- setText(text)
- })
- })
- } else if (AI == "Coze") {
- const node = document.querySelector(".b5gKALp6yXERRDn8TV4r")
- node[Object.keys(node)[0]].pendingProps.children[0].props.onSendMessage({ text, mentionList: [] })
- } else if (AI == "Chatglm") {
- fetch(`https://chatglm.cn/chatglm/backend-api/assistant/stream`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- "Authorization": `Bearer ${localStorage.token}`
- },
- body: JSON.stringify({
- "assistant_id": "65940acff94777010aa6b796",
- "conversation_id": localStorage.conversation_id || "",
- "meta_data": {
- "mention_conversation_id": "",
- "is_test": false,
- "input_question_type": "xxxx",
- "channel": "",
- "draft_id": ""
- }, "messages": [
- { "role": "user", "content": [{ "type": "text", "text": text }] }]
- })
- })
- .then(response => {
- if (response.status == 200) {
- return response.body.getReader()
- } else {
- throw Error("授权失败")
- }
- })
- .then(reader => {
- let text = ""
- const decoder = new TextDecoder();
- window.setTimeout(async () => {
- while (true) {
- const { done, value } = await reader.read();
- if (done) {
- await execInZotero(`
- let task = window.Meet.tasks[window.Meet.tasks.length-1]
- task.responseText = ${JSON.stringify(text)};
- task.type = "done";
- task.responseType = "markdown"
- `)
- break
- }
- try {
- const newLines = decoder.decode(value, { stream: true })
- for (let line of newLines.match(/event:message\ndata: .+/g)) {
- try {
- const data = JSON.parse(line.split("data: ")[1])
- if (localStorage.conversation_id.length == 0) {
- localStorage.conversation_id = data.conversation_id
- }
- text = data.parts[0].content[0].text
- } catch { }
- execInZotero(`
- let task = window.Meet.tasks[window.Meet.tasks.length-1]
- task.responseText = ${JSON.stringify(text)};
- task.type = "pending";
- task.responseType = "markdown"
- `)
- }
- } catch (e) {
- console.log(e)
- }
-
- }
- }, 0)
- })
- .catch(e => {
- console.log(e)
- localStorage.conversation_id = ""
- })
-
- } else if (AI == "Yiyan") {
- const node = document.querySelector("#eb_model_footer")
- node[Object.keys(node)[1]].children[2].props.children[2].props.children[0].props.setText(text);
- document.querySelector(".VAtmtpqL").click()
- } else if (AI == "Tongyi") {
- const node = document.querySelector(".inputField--PE5FhWzd").children[0]
- node[Object.keys(node)[1]].children[3].props.children[0].props.setText(text);
- window.setTimeout(async () => {
- const node2 = document.querySelector(".operateBtn--zFx6rSR0");
- node2[Object.keys(node2)[1]].onClick()
- })
- }
- }
-
- // 阻塞
- function sleep(ms) {
- return new Promise(resolve => setTimeout(resolve, ms));
- }
-
- GM_registerMenuCommand('🔗 运行', () => {
- isRunning = true
- window.alert("🔗 已运行")
- });
- GM_registerMenuCommand('🎊 断开', () => {
- isRunning = false
- window.alert("🎊 断开")
- });
-
-
- // 通信
- await sleep(3000)
- 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)
- } else if (AI == "Coze") {
- setText(task.requestText)
- } else if (AI == "Chatglm") {
- setText(task.requestText)
- } else if (AI == "Yiyan") {
- setText(task.requestText)
- } else if (AI == "Tongyi") {
- 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"
- const setZoteroText = async () => {
- 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)};
- `)
- }
- }
- if (AI == "ChatGPT") {
- type = "markdown"
- const outputEle = [...document.querySelectorAll('[data-testid^=conversation-turn]')].slice(-1)[0];
- const node = outputEle.querySelector("[data-message-author-role=assistant]")
- // const contentEle = outputEle.querySelector("div>div>div:nth-child(2)>div:nth-child(2)>div")
- isDone = Boolean(outputEle.querySelector("span[data-state=closed]"))
- text = node[Object.keys(node)[0]].alternate.alternate.pendingProps.children[1].props.messages[0].message.content.parts[0]
-
- await setZoteroText()
- } 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
- await setZoteroText()
- } 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
- await setZoteroText()
- } else if (AI == "Kimi") {
- // 无需这一步
- } else if (AI == "Coze") {
- const outputEle = document.querySelector(".message-group-wrapper");
- const contentEle = outputEle.querySelector("[data-testid='bot.ide.chat_area.message_box'] .flow-markdown-body")
- isDone = Boolean(outputEle.querySelector(".chat-uikit-message-box-container__message__message-box__footer").childNodes.length != 0)
- text = contentEle.innerHTML.replace(/<br .+?>/g, "").replace(/<hr .+?>/g, "<hr/>")
- await setZoteroText()
- } else if (AI == "Kimi") {
- // 无需这一步
- } else if (AI == "Yiyan") {
- const outputEle = document.querySelector(".ErXhAgf5 .RmHagX8t");
- const contentEle = outputEle.querySelector(".custom-html.md-stream-desktop")
- isDone = Boolean(outputEle.querySelector(".fXxD0Rtx"))
- text = contentEle.innerHTML.replace(/<br .+?>/g, "").replace(/<hr .+?>/g, "<hr/>")
- await setZoteroText()
- } else if (AI == "Tongyi") {
- const lastQuestion = [...document.querySelectorAll(".questionItem--dS3Alcnv")].slice(-1)[0]
- const outputEle = lastQuestion.nextElementSibling;
- const contentEle = outputEle.querySelector(".tongyi-ui-markdown")
- isDone = Boolean(outputEle.querySelector(".tools--IJfoLgka"))
- type = "markdown"
- text = contentEle[Object.keys(contentEle)[1]].children._owner.pendingProps.children
- .replace(/\[ty-private-cursor\]\(ty-private-cursor\)$/, "")
-
- await setZoteroText()
- }
- }
- }
- } catch (e) {
- console.log(e)
- }
- await sleep(100)
- }
- })();