chatgpt-retrieval-plugin

semantic search and retrieval of personal or organizational documents and chat

  1. // ==UserScript==
  2. // @name chatgpt-retrieval-plugin
  3. // @namespace http://tampermonkey.net/
  4. // @version 0.3
  5. // @description semantic search and retrieval of personal or organizational documents and chat
  6. // @author temberature@gmail.com
  7. // @match https://*/*
  8. // @grant GM_xmlhttpRequest
  9. // @run-at document-idle
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. (function () {
  14. 'use strict';
  15. if (!window.location.href.startsWith('https://chat.openai.com/')) {
  16. document.addEventListener('keydown', function (event) {
  17. if (event.ctrlKey && event.key === 'g') {
  18. event.preventDefault();
  19. const currentUrl = window.location.href;
  20. const chatUrl = `https://chat.openai.com/chat?url=${encodeURIComponent(currentUrl)}`;
  21. window.open(chatUrl, '_blank');
  22. }
  23. });
  24. return
  25. }
  26. let monitorReply2TranslateBack = false, monitorReply2quest = false;
  27. let translateMode = true;
  28. let form, submitButton, inputField, submitButtonClone, inputFieldClone;
  29. interceptSubmitBtn();
  30.  
  31. const observer = new MutationObserver(mutations => {
  32. mutations.forEach(mutation => {
  33. if (mutation.type === 'childList') {
  34. console.log(mutation.addedNodes)
  35. mutation.addedNodes.forEach(addedNode => {
  36. if (addedNode.nodeType === Node.ELEMENT_NODE && ((addedNode.classList.contains('overflow-hidden') && addedNode.classList.contains('w-full') && addedNode.classList.contains('h-full') && addedNode.classList.contains('relative')))) {
  37. interceptSubmitBtn();
  38. }
  39. if (addedNode.nodeType === Node.ELEMENT_NODE && (addedNode.classList.contains('px-2') &&
  40. addedNode.classList.contains('py-10') &&
  41. addedNode.classList.contains('relative') &&
  42. addedNode.classList.contains('w-full') &&
  43. addedNode.classList.contains('flex') &&
  44. addedNode.classList.contains('flex-col') &&
  45. addedNode.classList.contains('h-full'))) {
  46.  
  47. interceptSubmitBtn();
  48.  
  49. }
  50.  
  51. });
  52.  
  53. mutation.removedNodes.forEach(removedNode => {
  54. if (removedNode.nodeType === Node.ELEMENT_NODE && removedNode.classList.contains('btn') && removedNode.classList.contains('flex') && removedNode.classList.contains('justify-center') && removedNode.classList.contains('gap-2') && removedNode.classList.contains('btn-neutral') && removedNode.classList.contains('border-0') && removedNode.classList.contains('md:border') && removedNode.textContent.includes('Stop generating')) {
  55. const proseElements = document.querySelectorAll('.prose');
  56. const lastProseElement = proseElements[proseElements.length - 1];
  57. const form = document.querySelector('form.stretch');
  58. const submitButton = form.querySelector('div div:nth-child(2) > button');
  59. const inputField = form.querySelector('div:nth-child(2) textarea');
  60. if (monitorReply2quest) {
  61. quest(lastProseElement.textContent);
  62.  
  63. } else if (monitorReply2TranslateBack) {
  64. translateBack(lastProseElement.textContent);
  65. }
  66. }
  67. })
  68. }
  69. });
  70. });
  71.  
  72. observer.observe(document.body, { childList: true, subtree: true });
  73. // 定义翻译函数,用于翻译给定的文本
  74. const translateText = async (text) => {
  75. const url = 'https://translate.googleapis.com/translate_a/single?client=gtx&sl=zh-CN&tl=en&dt=t&q=' + encodeURI(text);
  76. const response = await fetch(url);
  77. const data = await response.json();
  78. return data[0][0][0];
  79. };
  80.  
  81. function interceptSubmitBtn() {
  82.  
  83. form = document.querySelector('form.stretch');
  84. submitButton = form.querySelector('div div:nth-child(2) > button');
  85. inputField = form.querySelector('div:nth-child(2) textarea');
  86. // 拦截表单提交事件,翻译输入内容并替换输入框中的内容
  87. if (!submitButton || !inputField) {
  88. return;
  89. }
  90.  
  91. submitButton.addEventListener('click', handleSubmit, { useCapture: true });
  92.  
  93. inputField.addEventListener("keydown", handleEnterDown, { useCapture: true });
  94. inputField.addEventListener("keyup", async function (event) {
  95. if (event.key === "Enter") {
  96. event.preventDefault();
  97. event.stopImmediatePropagation();
  98. }
  99. });
  100. inputField.addEventListener("keypress", async function (event) {
  101. if (event.key === "Enter") {
  102. event.preventDefault();
  103. event.stopImmediatePropagation();
  104. }
  105. });
  106.  
  107.  
  108. }
  109. async function handleEnterDown(event) {
  110. if (event.key === "Enter") {
  111. handleSubmit(event);
  112. }
  113. }
  114. async function handleSubmit(event) {
  115. const stage = submitButton.getAttribute('data-stage')
  116. const texts = inputField.value.split('|');
  117.  
  118. if ((stage && stage != 0) || !translateMode) {
  119. return;
  120. } else if (texts.length > 1 && ['默认模式', 'default', 'd'].includes(texts[0])) {
  121. inputField.value = texts[1];
  122. return;
  123. } else if (texts.length > 1 && ['切换模式', 'toggle', 't'].includes(texts[0])) {
  124. translateMode = !translateMode;
  125. inputField.value = texts[1];
  126. return;
  127. }
  128. event.preventDefault();
  129. event.stopImmediatePropagation();
  130. if (!+stage) {
  131. if (!monitorReply2quest && !monitorReply2TranslateBack) {
  132. translate();
  133. // Proceed with other steps like translation
  134. }
  135. }
  136.  
  137. }
  138. function getUrlParameter(name) {
  139. const urlParams = new URLSearchParams(window.location.search);
  140. return urlParams.get(name);
  141. }
  142. async function translate() {
  143. submitButton.setAttribute('data-stage', 'translating');
  144.  
  145. const inputText = inputField.value.trim();
  146. if (inputText.length === 0) {
  147. return;
  148. }
  149. inputField.value = "处理中...";
  150.  
  151. try {
  152. const apiResponseText = await enhanceQuestion(inputText);
  153. console.log('API response text:', apiResponseText);
  154. inputField.value = apiResponseText;
  155. submitButton.click();
  156. submitButton.setAttribute('data-stage', 0);
  157. monitorReply2TranslateBack = false;
  158. } catch (error) {
  159. console.error('Error:', error);
  160. alert(error);
  161. }
  162.  
  163.  
  164. }
  165.  
  166. function quest(reply) {
  167. submitButton.setAttribute('data-stage', 'questing');
  168.  
  169. if (reply.length === 0) {
  170. return;
  171. }
  172.  
  173. inputField.value = 'answer using English, as specific as possible: "' + reply + '"';
  174.  
  175. submitButton.click();
  176. monitorReply2quest = false;
  177. monitorReply2TranslateBack = true;
  178. }
  179. function translateBack(reply) {
  180. submitButton.setAttribute('data-stage', 'translateBacking');
  181. inputField.value = '翻译成中文,只返回中文: "' + reply + '"';
  182. submitButton.click();
  183. monitorReply2TranslateBack = false;
  184. submitButton.setAttribute('data-stage', 0);
  185. }
  186. async function enhanceQuestion(text) {
  187. const filters = getAllUrlParameters();
  188. return new Promise(async (resolve, reject) => {
  189. try {
  190. const response = await fetch('https://api.talkgpt.space/v1/questions/enhance', {
  191. method: 'POST',
  192. headers: {
  193. 'Content-Type': 'application/json'
  194. },
  195. body: JSON.stringify({ text, filter: filters })
  196. });
  197.  
  198. if (response.ok) {
  199. const data = await response.json();
  200. resolve(data.enhancedText);
  201. } else {
  202. const errorMessage = (await response.json()).message;
  203. console.error(errorMessage);
  204. reject(errorMessage);
  205. }
  206. } catch (error) {
  207. const errorMessage = `Error enhancing question: ${error.message}`;
  208. console.error(errorMessage);
  209. reject(errorMessage);
  210. }
  211. });
  212. }
  213.  
  214. function getAllUrlParameters() {
  215. const urlParams = new URLSearchParams(window.location.search);
  216. let filters = {};
  217.  
  218. for (const [key, value] of urlParams.entries()) {
  219. filters[key] = value;
  220. }
  221.  
  222. return filters;
  223. }
  224.  
  225.  
  226.  
  227. })();

QingJ © 2025

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