GPT Auto task

自动在网页上与chat gpt对话

目前为 2023-06-21 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @namespace https://greasyfork.org/zh-CN/users/1106595-ikkem-lin
  3. // @name GPT Auto task
  4. // @author Mark
  5. // @description 自动在网页上与chat gpt对话
  6. // @homepageURL https://github.com/IKKEM-Lin/gpt-auto-task
  7. // @version 0.0.4
  8. // @match *chat.openai.com/*
  9. // @run-at document-idle
  10. // ==/UserScript==
  11. (function () {
  12. "use strict";
  13. class GPT_ASK_LOOP {
  14. queue = [];
  15. responds = [];
  16. checkInterval = 10000;
  17. account = "";
  18. downloadBtn = null;
  19.  
  20. constructor(account) {
  21. this.responds = JSON.parse(
  22. localStorage.getItem("reaction_responds") || "[]"
  23. );
  24. const queueCache = JSON.parse(localStorage.getItem("task_queue") || "[]");
  25. const resSnippetIds = this.responds.map((respond) => respond.snippetId);
  26. this.queue = queueCache.filter((item) => !resSnippetIds.includes(item.id));
  27. this.account = account || Math.ceil(Math.random() * 1e10).toString(32);
  28. const btnWrap = document.createElement("div");
  29. btnWrap.innerHTML = `<button style="padding: 4px 8px;position: fixed;bottom: 20%;right: 8px;border-radius: 4px;background-color: #224466;color: #fff;">下载已生成结果(queue: ${this.queue.length}, res: ${this.responds.length})</button>`;
  30. this.downloadBtn = btnWrap.querySelector("button");
  31. this.downloadBtn.onclick = this.handleDownload.bind(this);
  32. document.body.appendChild(btnWrap);
  33. this.main();
  34. }
  35.  
  36. handleDownload() {
  37. const respond = JSON.parse(
  38. localStorage.getItem("reaction_responds") || "[]"
  39. );
  40. if (!respond.length) {
  41. return;
  42. }
  43. const result = respond.map((item) => {
  44. const ele = document.createElement("div");
  45. ele.innerHTML = item.reaction;
  46. const res = Array.from(ele.querySelectorAll("code")).map(
  47. (el) => el.innerText
  48. );
  49. return { ...item, reaction: res };
  50. });
  51. const now = new Date();
  52. this.downloadFile(
  53. JSON.stringify(result),
  54. `${now.getFullYear()}-${now.getMonth() + 1
  55. }-${now.getDate()}-${now.getHours()}${now.getMinutes()}${now.getSeconds()}.json`
  56. );
  57. }
  58.  
  59. downloadFile(data, fileName) {
  60. const a = document.createElement("a");
  61. document.body.appendChild(a);
  62. a.style = "display: none";
  63. const blob = new Blob([data], {
  64. type: "application/octet-stream",
  65. });
  66. const url = window.URL.createObjectURL(blob);
  67. a.href = url;
  68. a.download = fileName;
  69. a.click();
  70. window.URL.revokeObjectURL(url);
  71. }
  72.  
  73. async report() {
  74. await fetch("https://gpt-hit.deno.dev/api/update", {
  75. method: "POST",
  76. body: JSON.stringify({
  77. account: this.account,
  78. reaction_count: this.responds.length,
  79. queue_count: this.queue.length,
  80. }),
  81. }).catch((err) => {
  82. console.error({ err });
  83. });
  84. }
  85.  
  86. genPrompt(content) {
  87. return `${localStorage.getItem("mock_prompt")}
  88.  
  89. ''' ${content} ''' `;
  90. }
  91.  
  92. getTask() {
  93. this.report();
  94. if (this.downloadBtn) {
  95. this.downloadBtn.innerText = `下载已生成结果(queue: ${this.queue.length}, res: ${this.responds.length})`;
  96. }
  97. const task = this.queue[0];
  98. if (!task) {
  99. console.log("任务队列为空");
  100. return;
  101. }
  102. return async () => {
  103. const { article_id, id, content } = task;
  104. console.log(`开始触发 ${article_id}-${id}, ${new Date().toTimeString()}`);
  105. const prompt = this.genPrompt(content);
  106. const result = await this.trigger(prompt);
  107. return { articleId: article_id, snippetId: id, reaction: result };
  108. // console.log("result:", result);
  109. };
  110. }
  111.  
  112. saveRespond(respond) {
  113. const { snippetId } = respond;
  114. this.responds.push(respond);
  115. this.queue = this.queue.filter((item) => item.id !== snippetId);
  116. localStorage.setItem("task_queue", JSON.stringify(this.queue));
  117. localStorage.setItem("reaction_responds", JSON.stringify(this.responds));
  118. }
  119.  
  120. sleep(duration) {
  121. return new Promise((resolve, reject) => {
  122. setTimeout(() => {
  123. resolve(true);
  124. }, duration);
  125. });
  126. }
  127.  
  128. trigger(prompt, checkInterval = this.checkInterval) {
  129. return new Promise((resolve, reject) => {
  130. const textEl = document.querySelector("#prompt-textarea");
  131. const submitEl = document.querySelector("#prompt-textarea + button");
  132. textEl.value = prompt; //`你好, 帮我算下${Math.floor(Math.random() * 10000)}开平方的结果`;
  133. textEl.dispatchEvent(new Event("input", { bubbles: true }));
  134. setTimeout(() => {
  135. submitEl.click();
  136.  
  137. let resCache = null;
  138. (async () => {
  139. while (true) {
  140. await this.sleep(checkInterval);
  141. const result = Array.from(document.querySelectorAll("main .group"));
  142. const temp = result[result.length - 1];
  143. if (!temp) {
  144. continue;
  145. }
  146. if (resCache === temp.innerHTML) {
  147. // console.log("匹配,resCache:", resCache);
  148. resolve(resCache);
  149. break;
  150. }
  151. resCache = temp.innerHTML;
  152. console.log(`${checkInterval / 1000}s后再次检查结果`);
  153. }
  154. })();
  155. }, 4000);
  156. });
  157. }
  158.  
  159. async main(sleepTime = 5000) {
  160. while (true) {
  161. // {0: gpt-3.5, 1: gpt-4, 2: gpt-4 mobile}
  162. const modelNum = localStorage.getItem("model_number") || 1;
  163. const gpt4btn = document.querySelectorAll("ul > li > button.cursor-pointer")[modelNum];
  164. if (gpt4btn) {
  165. gpt4btn.firstChild.click()
  166. }
  167. await this.sleep(sleepTime/2);
  168. const task = this.getTask();
  169. if (!task) {
  170. await this.sleep(5 * 60 * 1000);
  171. continue;
  172. }
  173.  
  174. const result = await task();
  175. this.saveRespond(result);
  176. console.log(`${sleepTime / 1000}s后将再次触发`);
  177. const newChatBtn = document.querySelector("nav>div.mb-1>a:first-child");
  178. newChatBtn.click();
  179. await this.sleep(sleepTime/2);
  180. }
  181. }
  182. }
  183.  
  184. function start() {
  185. const nameEl = document.querySelector(
  186. "nav > div:last-child > div:last-child"
  187. )
  188. const name = nameEl && nameEl.innerText;
  189. if (name) {
  190. new GPT_ASK_LOOP(name);
  191. } else {
  192. setTimeout(() => {
  193. start();
  194. }, 5000);
  195. }
  196. }
  197. start();
  198.  
  199. })();