Zotero GPT Connector

Connector

目前為 2023-11-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Zotero GPT Connector
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.1
  5. // @description Connector
  6. // @author Polygon
  7. // @match https://chat.openai.com/*
  8. // @icon https://cdn.oaistatic.com/_next/static/media/favicon-32x32.be48395e.png
  9. // @grant GM_xmlhttpRequest
  10. // @grant unsafeWindow
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. (async function () {
  15. 'use strict';
  16. // 在Zotero中执行代码
  17. function execInZotero(code) {
  18. return new Promise((resolve, reject) => {
  19. GM_xmlhttpRequest({
  20. method: "POST",
  21. url: "http://127.0.0.1:23119/zoterogpt",
  22. headers: {
  23. "Content-Type": "application/json",
  24. },
  25. responseType: "json",
  26. data: JSON.stringify({code}),
  27. onload: function (response) {
  28. if (response.status >= 200 && response.status < 300) {
  29. resolve(response.response.result);
  30. } else {
  31. reject(new Error(`Request failed with status: ${response.status}`));
  32. }
  33. },
  34. onerror: function (error) {
  35. reject(new Error('Network error'));
  36. }
  37. });
  38. });
  39. }
  40.  
  41. // 设定ChatGPT输入框文本并发送
  42. const setText = (text) => {
  43. // 获取 input 输入框的dom对象
  44. var element_input = window.document.querySelector('#prompt-textarea');
  45. // 修改input的值
  46. element_input.value = text;
  47. // 设置输入框的 input 事件
  48. var event = new InputEvent('input', {
  49. 'bubbles': true,
  50. 'cancelable': true,
  51. });
  52. element_input.dispatchEvent(event);
  53. document.querySelector("[data-testid=send-button]").click()
  54. setTimeout(() => {
  55. document.querySelector("[data-testid=send-button]").click()
  56. }, 100)
  57. }
  58.  
  59. function sleep(ms) {
  60. return new Promise(resolve => setTimeout(resolve, ms));
  61. }
  62.  
  63. while (true) {
  64. console.log("running...")
  65. try {
  66. const result = await execInZotero(`
  67. if (!window.Meet.tasks){
  68. window.Meet.tasks = []
  69. } else {
  70. window.Meet.tasks
  71. }
  72. `)
  73. const tasks = result;
  74. if (!tasks || tasks.length == 0) {
  75. await sleep(500)
  76. continue
  77. }
  78. const task = tasks.slice(-1)[0]
  79. if (task.type == "request") {
  80. // 操作浏览器提问
  81. let getUserQuestionNum = () => document.querySelectorAll("[data-message-author-role=user]").length
  82. const questionNum = getUserQuestionNum()
  83. console.log(task.text)
  84. setText(task.text)
  85. while (getUserQuestionNum() == questionNum) {
  86. await sleep(100)
  87. }
  88. await execInZotero(`
  89. window.Meet.tasks.push({
  90. type: "response",
  91. text: "处理中..."
  92. })
  93. `)
  94. } else if (task.type == "response") {
  95. const outputEle = [...document.querySelectorAll('[data-testid^=conversation-turn]')].slice(-1)[0];
  96. const contentEle = outputEle.querySelector(".gap-3") || outputEle
  97. const isDone = contentEle.nextElementSibling.querySelector("button")
  98. const text = contentEle.querySelector(".markdown").innerHTML
  99. // 读取浏览器数据
  100. await execInZotero(`
  101. const task = window.Meet.tasks.slice(-1)[0]
  102. if (task.type == "response") {
  103. task.text = \`${text}\`;
  104. task.isDone = ${isDone ? "true" : "false"}
  105. }
  106. `)
  107. }
  108. } catch (e) {
  109. console.log(e)
  110. }
  111. await sleep(10)
  112. }
  113. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址