GPT Auto task

自动在网页上与chat gpt对话

当前为 2023-06-20 提交的版本,查看 最新版本

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Greasemonkey 油猴子Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Violentmonkey 暴力猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴Userscripts ,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey 篡改猴,才能安装此脚本。

您需要先安装一款用户脚本管理器扩展后才能安装此脚本。

(我已经安装了用户脚本管理器,让我安装!)

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展,比如 Stylus,才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

您需要先安装一款用户样式管理器扩展后才能安装此样式。

(我已经安装了用户样式管理器,让我安装!)

// ==UserScript==
// @namespace         https://greasyfork.org/zh-CN/users/1106595-ikkem-lin
// @name              GPT Auto task
// @author            Mark
// @description       自动在网页上与chat gpt对话
// @homepageURL       https://github.com/IKKEM-Lin/gpt-auto-task
// @version           0.0.3
// @match             *chat.openai.com/*
// @run-at            document-idle
// ==/UserScript==
(function () {
    "use strict";
    class GPT_ASK_LOOP {
        queue = [];
        responds = [];
        checkInterval = 10000;
        account = "";
        downloadBtn = null;

        constructor(account) {
            this.responds = JSON.parse(
                localStorage.getItem("reaction_responds") || "[]"
            );
            const queueCache = JSON.parse(localStorage.getItem("task_queue") || "[]");
            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() {
            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,
                }),
            }).catch((err) => {
                console.error({ err });
            });
        }

        genPrompt(content) {
            return `${localStorage.getItem("mock_prompt")}

            ''' ${content} ''' `;
        }

        getTask() {
            this.report();
            if (this.downloadBtn) {
                this.downloadBtn.innerText = `下载已生成结果(queue: ${this.queue.length}, res: ${this.responds.length})`;
            }
            const task = this.queue[0];
            if (!task) {
                console.log("任务队列为空");
                return;
            }
            return async () => {
                const { article_id, id, content } = task;
                console.log(`开始触发 ${article_id}-${id}, ${new Date().toTimeString()}`);
                const prompt = this.genPrompt(content);
                const result = await this.trigger(prompt);
                return { articleId: article_id, snippetId: id, reaction: result };
                // console.log("result:", result);
            };
        }

        saveRespond(respond) {
            const { snippetId } = respond;
            this.responds.push(respond);
            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);
                                resolve(resCache);
                                break;
                            }
                            resCache = temp.innerHTML;
                            console.log(`${checkInterval / 1000}s后再次检查结果`);
                        }
                    })();
                }, 4000);
            });
        }

        async main(sleepTime = 5000) {
            while (true) {
                const task = this.getTask();
                if (!task) {
                    await this.sleep(5 * 60 * 1000);
                    continue;
                }

                const result = await task();
                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);
            }
        }
    }

    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();

})();