您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
根据缓存中的task_queue自动在网页上与chat gpt对话
当前为
// ==UserScript== // @namespace https://greasyfork.org/zh-CN/users/1106595-ikkem-lin // @name GPT Auto task // @author Mark // @description 根据缓存中的task_queue自动在网页上与chat gpt对话 // @homepageURL https://github.com/IKKEM-Lin/gpt-auto-task // @version 0.0.14 // @match *chat.openai.com/* // @run-at document-idle // ==/UserScript== (function () { "use strict"; class GPT_ASK_LOOP { queue = []; abstract = []; responds = []; checkInterval = 20000; account = ""; downloadBtn = null; retrying = false; defaultMode = 2; constructor(account) { this.responds = JSON.parse( localStorage.getItem("reaction_responds") || "[]" ); const queueCache = JSON.parse(localStorage.getItem("task_queue") || "[]"); this.abstract = JSON.parse(localStorage.getItem("task_abstract") || "[]"); const resSnippetIds = this.responds.map((respond) => respond.snippetId); this.queue = queueCache.filter((item) => !resSnippetIds.includes(item.id)); this.account = account || Math.ceil(Math.random() * 1e10).toString(32); const btnWrap = document.createElement("div"); 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>`; this.downloadBtn = btnWrap.querySelector("button"); this.downloadBtn.onclick = this.handleDownload.bind(this); document.body.appendChild(btnWrap); this.main(); } handleDownload() { const respond = JSON.parse( localStorage.getItem("reaction_responds") || "[]" ); if (!respond.length) { return; } const result = respond.map((item) => { const ele = document.createElement("div"); ele.innerHTML = item.reaction; const res = Array.from(ele.querySelectorAll("code")).map( (el) => el.innerText ); return { ...item, reaction: res }; }); const now = new Date(); this.downloadFile( JSON.stringify(result), `${now.getFullYear()}-${now.getMonth() + 1 }-${now.getDate()}-${now.getHours()}${now.getMinutes()}${now.getSeconds()}.json` ); } downloadFile(data, fileName) { const a = document.createElement("a"); document.body.appendChild(a); a.style = "display: none"; const blob = new Blob([data], { type: "application/octet-stream", }); const url = window.URL.createObjectURL(blob); a.href = url; a.download = fileName; a.click(); window.URL.revokeObjectURL(url); } async report(tip = "") { await fetch("https://gpt-hit.deno.dev/api/update", { method: "POST", body: JSON.stringify({ account: this.account, reaction_count: this.responds.length, queue_count: this.queue.length, tip: tip, }), }).catch((err) => { console.error({ err }); }); } genPrompt(content, step = 1) { return step === 1 ? `${localStorage.getItem("mock_prompt"+step)} ''' ${content} ''' ` : localStorage.getItem("mock_prompt"+step); } getTask() { if (this.downloadBtn) { this.downloadBtn.innerText = `下载已生成结果(queue: ${this.queue.length}, res: ${this.responds.length})`; } const task = this.queue[0]; this.report(task && `Working on articleId: ${task.article_id}, snippetId: ${task.id}` || ""); if (!task) { console.log("任务队列为空"); return; } return async () => { const { article_id, id, content } = task; const relatedAbstract = this.abstract.find((item) => item.article_id === article_id)?.content || ""; console.log(`开始触发 ${article_id}-${id}, ${new Date().toTimeString()}`); const promptContent = ` ${relatedAbstract} ${content} ` const prompt1 = this.genPrompt(promptContent, 1); const prompt2 = this.genPrompt(promptContent, 2); const result1 = await this.trigger(prompt1).catch((err) => { return null }); if (!result1) { return null; } const result2 = await this.trigger(prompt2).catch((err) => { return null }); if (!result2) { return { articleId: article_id, snippetId: id, reaction: result1 }; } return { articleId: article_id, snippetId: id, reaction: result2 }; // console.log("result:", result); }; } saveRespond(respond) { const { snippetId } = respond; this.responds.push({...respond, createdTime: new Date().valueOf()}); this.queue = this.queue.filter((item) => item.id !== snippetId); localStorage.setItem("task_queue", JSON.stringify(this.queue)); localStorage.setItem("reaction_responds", JSON.stringify(this.responds)); } sleep(duration) { return new Promise((resolve, reject) => { setTimeout(() => { resolve(true); }, duration); }); } trigger(prompt, checkInterval = this.checkInterval) { return new Promise((resolve, reject) => { const textEl = document.querySelector("#prompt-textarea"); const submitEl = document.querySelector("#prompt-textarea + button"); textEl.value = prompt; //`你好, 帮我算下${Math.floor(Math.random() * 10000)}开平方的结果`; textEl.dispatchEvent(new Event("input", { bubbles: true })); setTimeout(() => { submitEl.click(); let resCache = null; (async () => { while (true) { await this.sleep(checkInterval); const result = Array.from(document.querySelectorAll("main .group")); const temp = result[result.length - 1]; if (!temp) { continue; } if (resCache === temp.innerHTML) { // console.log("匹配,resCache:", resCache); const validateResult = await this.validate(resCache).catch(err => { reject(null); return; }) if (validateResult === true) { resolve(resCache); break; } else if (validateResult === false) { continue; } reject(null); break; } resCache = temp.innerHTML; console.log(`${checkInterval / 1000}s后再次检查结果`); } })(); }, 4000); }); } async validate(innerHTML) { const buttons = document.querySelectorAll("form div button.btn-neutral"); const errorBtn = document.querySelectorAll("form div button.btn-primary"); // 如果触发gpt-4 3小时25次限制 if (!buttons[0] && !errorBtn[0] && innerHTML.includes("usage cap")) { console.error("触发gpt-4 3小时25次限制,等待10min后重试") await this.sleep(10 * 60 * 1000); throw new Error("触发gpt-4 3小时25次限制"); } // 如果openAI服务器报错未返回结果 if (errorBtn[0]) { // && innerHTML.includes("wrong")) { if (this.retrying) { this.retrying = false; return true; } errorBtn[0].click(); this.retrying = true; return false; } // 如果输出结果未包含code标签 if (!innerHTML.includes("</code>")) { if (this.retrying) { this.retrying = false; return true; } console.error("未输出yaml结构,重试一次") buttons[0].click(); this.retrying = true; return false; } this.retrying = false; // 如果还未完全输出 if (buttons.length > 1) { buttons[buttons.length - 1].click(); return false; } return true; } async main(sleepTime = 5000) { while (true) { // {0: gpt-3.5, 1: gpt-4, 2: gpt-4 mobile} const modelNum = +localStorage.getItem("model_number") || this.defaultMode; const gpt4btn = document.querySelectorAll("ul > li > button.cursor-pointer")[modelNum]; console.log(`当前模型为:${gpt4btn.innerText}`); if (gpt4btn) { gpt4btn.firstChild.click() } await this.sleep(sleepTime/2); if (modelNum===1 && !location.href.endsWith("gpt-4")) { console.log("未切换到gpt-4模式, 5分钟后重试"); const maxTime = Math.max.apply(null, this.responds.map(item => item.createdTime).filter(item => item).push(0)) const diff = new Date().valueOf() - maxTime; if (maxTime && diff > 1.5 * 60 * 60 * 1000) { location.reload(); break; } this.report(`触发gpt-4 3小时25次限制,上次运行时间:${new Date(maxTime).toLocaleString()}`); await this.sleep(5 * 60 * 1000); const newChatBtn = document.querySelector("nav>div.mb-1>a:first-child"); newChatBtn.click(); continue; } const task = this.getTask(); if (!task) { await this.sleep(5 * 60 * 1000); continue; } const result = await task(); if (result) { this.saveRespond(result); } console.log(`${sleepTime / 1000}s后将再次触发`); const newChatBtn = document.querySelector("nav>div.mb-1>a:first-child"); newChatBtn.click(); await this.sleep(sleepTime/2); } } } function start() { const nameEl = document.querySelector( "nav > div:last-child > div:last-child" ) const name = nameEl && nameEl.innerText; if (name) { new GPT_ASK_LOOP(name); } else { setTimeout(() => { start(); }, 5000); } } start(); })();