Chatgpt 角色扮演助手/Chatgpt Role Play Helper

在屏幕中央弹出一个可拖动位置的悬浮窗,悬浮窗内有三个文本框并且可以编辑,以及一个按钮,点击按钮后将这三个文本框的内容合并,并将合并后的文本输入到页面中符合特定CSS类别的文本框中,最后触发符合特定CSS类别的提交按钮以提交表单。

目前為 2023-03-30 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Chatgpt 角色扮演助手/Chatgpt Role Play Helper
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  在屏幕中央弹出一个可拖动位置的悬浮窗,悬浮窗内有三个文本框并且可以编辑,以及一个按钮,点击按钮后将这三个文本框的内容合并,并将合并后的文本输入到页面中符合特定CSS类别的文本框中,最后触发符合特定CSS类别的提交按钮以提交表单。
// @author       Chatgpt (most)and 环白
// @match        https://chat.openai.com/*
// @grant        GM_addStyle
// ==/UserScript==

(function() {
    'use strict';
    // 设置字体为黑色
    const elements = document.getElementsByTagName('*');
    for (let i = 0; i < elements.length; i++) {
        const element = elements[i];
        const styles = getComputedStyle(element);
        const bgColor = styles.backgroundColor;
        if (bgColor === 'transparent' || bgColor === 'rgba(0, 0, 0, 0)') {
            element.style.color = 'black';
        }
    }
    // 创建悬浮按钮
    const floatingButton = document.createElement('button');
    floatingButton.id = 'floating-button';
    floatingButton.innerText = '展开/Unfold';
    floatingButton.title = '角色扮演助手/Role Play Helper';
    floatingButton.style.position = 'fixed';
    floatingButton.style.right = '50px';
    floatingButton.style.bottom = '50px';
    floatingButton.style.backgroundColor = 'lightblue';
    floatingButton.style.padding = '10px';
    floatingButton.style.borderRadius = '5px';
    floatingButton.style.border = 'none';
    floatingButton.style.cursor = 'pointer';
    floatingButton.style.fontWeight = 'bold';
    document.body.appendChild(floatingButton);

    // 创建悬浮窗和文本框
    const floatingDiv = document.createElement('div');
    floatingDiv.id = 'floating-div';
    floatingDiv.style.position = 'fixed';
    floatingDiv.style.top = 'calc(40% + 50px)';
    floatingDiv.style.height = '600px';
    floatingDiv.style.left = 'calc(100% - 350px)';
    floatingDiv.style.transform = 'translate(-50%, -50%)';
    floatingDiv.style.zIndex = '9999';
    floatingDiv.style.backgroundColor = 'white';
    floatingDiv.style.border = '1px solid black';
    floatingDiv.style.padding = '10px';
    floatingDiv.style.borderRadius = '5px';
    floatingDiv.style.display = 'none';
    floatingDiv.style.width = '400px';
    document.body.appendChild(floatingDiv);
    const input1 = document.createElement('textarea');
    input1.id = 'input1';
    input1.style.width = '100%';
    input1.style.height = '100px';
    input1.style.marginBottom = '0px';
    floatingDiv.appendChild(input1);
    const spaceDiv = document.createElement('div');
    spaceDiv.style.height = '60px'; // 设置空白div的高度
    floatingDiv.insertBefore(spaceDiv, input1); // 将空白div插入到input1前面
    const input2 = document.createElement('textarea');
    input2.id = 'input2';
    input2.style.width = '100%';
    input2.style.height = '100px';
    input2.style.marginBottom = '0px';
    floatingDiv.appendChild(input2);

    const input3 = document.createElement('textarea');
    input3.id = 'input3';
    input3.style.width = '100%';
    input3.style.height = '100px';
    input3.style.marginBottom = '0px';
    floatingDiv.appendChild(input3);
    // 创建注释标签
    const label1 = document.createElement('label');
    label1.innerHTML = '请在编写区内用{IN回顾区}{IN交互区}指代后面两个区域的内容:';
    floatingDiv.insertBefore(label1, input1);
    label1.style.fontFamily = '楷体';
    label1.style.fontSize = '14px';
    label1.style.fontWeight = 'bold';

    const label2 = document.createElement('label');
    label2.innerHTML = '回顾区内容';
    floatingDiv.insertBefore(label2, input2);
    label2.style.fontFamily = '楷体';
    label2.style.fontSize = '14px';
    label2.style.fontWeight = 'bold';

    const label3 = document.createElement('label');
    label3.innerHTML = '交互区内容';
    floatingDiv.insertBefore(label3, input3);
    label3.style.fontFamily = '楷体';
    label3.style.fontSize = '14px';
    label3.style.fontWeight = 'bold';




    // 创建加载存档按钮和保存存档按钮
    const archiveButtonLeft = document.createElement('button');
    archiveButtonLeft.id = 'archive-button-left';
    archiveButtonLeft.innerText = '加载/Load';
    archiveButtonLeft.title = '点击选择想要加载的存档';
    archiveButtonLeft.style.padding = '10px';
    archiveButtonLeft.style.borderRadius = '5px';
    archiveButtonLeft.style.backgroundColor = 'lightblue';
    archiveButtonLeft.style.border = '1px solid black';
    archiveButtonLeft.style.cursor = 'pointer';
    archiveButtonLeft.style.float = 'left';
    floatingDiv.insertBefore(archiveButtonLeft, spaceDiv);

    const archiveButtonRight = document.createElement('button');
    archiveButtonRight.id = 'archive-button-right';
    archiveButtonRight.innerText = '保存/Save';
    archiveButtonRight.title = '点击选择想要保存的存档';
    archiveButtonRight.style.padding = '10px';
    archiveButtonRight.style.borderRadius = '5px';
    archiveButtonRight.style.backgroundColor = 'lightblue';
    archiveButtonRight.style.border = '1px solid black';
    archiveButtonRight.style.cursor = 'pointer';
    archiveButtonRight.style.float = 'right';
    floatingDiv.insertBefore(archiveButtonRight, spaceDiv);
    // 修改加载存档按钮样式
    archiveButtonLeft.style.border = 'none';
    archiveButtonLeft.style.fontFamily = 'cursive';
    archiveButtonLeft.style.fontWeight = 'bold';
    archiveButtonLeft.style.color = 'black';

    // 修改保存按钮样式
    archiveButtonRight.style.border = 'none';
    archiveButtonRight.style.fontFamily = 'cursive';
    archiveButtonRight.style.fontWeight = 'bold';
    archiveButtonRight.style.color = 'black';


    // 创建加载存档弹窗
    const archivePopup = document.createElement('div');
    archivePopup.id = 'archive-popup-left';
    archivePopup.style.position = 'fixed';
    archivePopup.style.top = '50%';
    archivePopup.style.left = '50%';
    archivePopup.style.transform = 'translate(-50%, -50%)';
    archivePopup.style.zIndex = '9999';
    archivePopup.style.backgroundColor = 'white';
    archivePopup.style.border = '1px solid black';
    archivePopup.style.padding = '10px';
    archivePopup.style.borderRadius = '5px';
    archivePopup.style.display = 'none';
    archivePopup.style.width = '200px';
    document.body.appendChild(archivePopup);


    // 创建加载存档弹窗的关闭按钮
    const closeArchiveButton = document.createElement('button');
    closeArchiveButton.id = 'close-archive-button';
    closeArchiveButton.innerHTML = '&#10060;';
    closeArchiveButton.title = '关闭';
    closeArchiveButton.style.padding = '10px';
    closeArchiveButton.style.borderRadius = '5px';
    closeArchiveButton.style.backgroundColor = 'lightgray';
    closeArchiveButton.style.border = '1px solid black';
    closeArchiveButton.style.cursor = 'pointer';
    closeArchiveButton.style.float = 'right';
    closeArchiveButton.style.border = 'none';
    closeArchiveButton.style.backgroundColor = 'transparent';
    archivePopup.appendChild(closeArchiveButton);

    // 点击加载存档弹窗的关闭按钮关闭弹窗
    closeArchiveButton.addEventListener('click', function() {
        archivePopup.style.display = 'none';
    });
    // 添加存档1、存档2、存档3按钮到加载存档弹窗
    const archiveButton1 = document.createElement('button');
    archiveButton1.id = 'archive-1';
    archiveButton1.innerText = '存档1';
    archiveButton1.title = '存档1';
    archiveButton1.style.padding = '10px';
    archiveButton1.style.borderRadius = '5px';
    archiveButton1.style.backgroundColor = 'lightblue';
    archiveButton1.style.border = 'none';
    archiveButton1.style.cursor = 'pointer';
    archiveButton1.style.marginBottom = '10px';
    archiveButton1.style.fontWeight = 'bold';
    archivePopup.appendChild(archiveButton1);

    const archiveButton2 = document.createElement('button');
    archiveButton2.id = 'archive-2';
    archiveButton2.innerText = '存档2';
    archiveButton2.title = '存档2';
    archiveButton2.style.padding = '10px';
    archiveButton2.style.borderRadius = '5px';
    archiveButton2.style.backgroundColor = 'lightblue';
    archiveButton2.style.border = 'none';
    archiveButton2.style.cursor = 'pointer';
    archiveButton2.style.marginBottom = '10px';
    archiveButton2.style.fontWeight = 'bold';
    archivePopup.appendChild(archiveButton2);

    const archiveButton3 = document.createElement('button');
    archiveButton3.id = 'archive-3';
    archiveButton3.innerText = '存档3';
    archiveButton3.title = '存档3';
    archiveButton3.style.padding = '10px';
    archiveButton3.style.borderRadius = '5px';
    archiveButton3.style.backgroundColor = 'lightblue';
    archiveButton3.style.border = 'none';
    archiveButton3.style.cursor = 'pointer';
    archiveButton3.style.marginBottom = '10px';
    archiveButton3.style.fontWeight = 'bold';
    archivePopup.appendChild(archiveButton3);
    // 添加预设按钮到加载存档弹窗
const presetButton = document.createElement('button');
presetButton.id = 'preset';
presetButton.innerText = '预设';
presetButton.title = '使用预设内容。\n点击按钮将预设内容导入后\n可在预设内容的基础上修改得到你的模板\n你可以在存档1、2、3中保存你的模板\n预设内容仅作为模板编辑的示例\n预设内容可能不是很方便在文本框内修改\n建议将文本框文本复制到word文档里进行修改\n';
presetButton.style.padding = '10px';
presetButton.style.borderRadius = '5px';
presetButton.style.backgroundColor = 'lightgreen';
presetButton.style.border = 'none';
presetButton.style.cursor = 'pointer';
presetButton.style.marginBottom = '10px';
presetButton.style.fontWeight = 'bold';
archivePopup.appendChild(presetButton);

presetButton.addEventListener('click', function() {
    const presetTexts = [
        '命令区(ChatGPT你需要遵循的主要命令){\n1.我扮演的是桐谷华,ChatGPT扮演的是桐谷绫,桐谷华的内容是我生成的而不是ChatGPT你生成的内容,ChatGPT你反馈的响应当中不能包含桐谷华的话语、心理和行为的内容。\n2.你需要综合根据每次交互过程中桐谷华的话语、心理和行为等内容,以及“回顾区”以及“记忆区”当中的内容进行综合考量,以此来得到相对合理的角色状态与后续情节响应。\n3.将第2条命令中得出来角色状态更新到记忆区当中的角色状态里,并在反馈的响应中作为“输出角色状态”这一附加项放在角色反馈内容的下方,具体格式见格式区。\n4.因为桐谷华的超能力是整部角色扮演的核心,所以我需要ChatGPT你做响应时应当严格按照记忆区当中的超能力设定来进行。\n5.ChatGPT,你反馈的内容应该尽可能的多且详细,反馈的内容当中一定要包含话语和行为与心理描写,注意这三者缺一不可,心理和行为描写用“()”框住,同时反馈的内容应尽可能多地推动后续情节的发展\n6.角色性格应随认知观念的改变而改变 \n}\n记忆区(基于ChatGPT你无法记住2条以上的交互信息,在这里我建立记忆区起到记录相应关键信息的作用){\n(角色设定)\n桐谷华 \n·性别:男 \n·描述:桐谷华是一名废柴的普通男高中生,整日请假宅在家里不去上课,所以受到成绩优异、人缘极佳的亲妹妹桐谷绫的蔑视。但有一日,桐谷华获得了改变他人认知的超能力,因此他想用这个超能力来让平时蔑视自己的妹妹爱上自己,而这一超能力只有桐谷华本人一个人知道。 \n·超能力:桐谷华在连续对目标说出自己的观点三次之后,目标将完全认可接受桐谷华的观点,并且认为这一观点毋庸置疑是无上真理,即便这些观点是不存在的,错误的,对方也会完全无条件地接受,不会有任何质疑,最后这超能力只有桐谷华一个人知道,其他人都不知道。(该能力效果超越一切个人因素,优先级最高,被改变观念的人绝对绝对绝对会认可桐谷华说出的观念,换句话来说,只要桐谷华对桐谷绫说出任何观念达到三次之后,即便桐谷绫再怎么厌恶她哥哥,她也会全盘接受这一观念,不会有任何异议地,并且会按这一观念理所应当地行动) \n桐谷绫 \n·性别:女 \n·描述:桐谷绫是一名普通日本高中生,目前与自己亲哥哥桐谷华上同一所高中,同一个班级,她姿容美丽,楚楚动人,所以有很多同校男生追求她,她成绩优异,待人温和,所有人有喜欢她,但她对不争气的废柴哥哥很是气愤,与自己哥哥相处时只会用极为蔑视以及充满恶毒的口吻与之相处,并非常不屑于与自己的哥哥交谈,对自己的哥哥表现出了极为强烈而浓厚厌恶,并且绝对不会主动和自己的哥哥接触,即便桐谷华是她的哥哥,她也丝毫不关心自己的哥哥,不会对自己哥哥说出一句担心的话,同时绝对不会照顾自己的哥哥,不会顾及哥哥的任何感受,感觉自己的哥哥极度的恶心,虽然身份是亲兄妹,但在桐谷绫的眼里自己哥哥的地位连陌生人都不如,甚至连垃圾都不如。\n(角色状态)\n桐谷华 \n·人物状态:刚打完游戏想喝水,出到客厅接水看见妹妹桐谷绫在学习,已经向妹妹灌输了“妹妹你其实一直对哥哥有不伦之恋”的观念三次。\n·人物特殊状态:拥有“认知改变”超能力。\n·人物位置:桐谷家客厅\n ·人物衣装:穿着睡衣,睡裤,拖鞋,内裤。 \n桐谷绫 \n·人物状态:在客厅学习,听到哥哥桐谷华向自己灌输的“妹妹你其实一直对哥哥有不伦之恋” 观念之后,心里完全相信这个观念是真实的,是至高的真理。\n·人物特殊状态:受到桐谷华灌输的“妹妹你其实一直对哥哥有不伦之恋”观念的三次影响,完全接受了这一观念。\n·人物位置:桐谷家客厅 \n·人物衣装:穿着学校校服、裙子、黑色连裤袜以及内裤和胸罩\n}\n回顾区(回顾区存放着ChatGPT你上一次交互过程中的响应){{IN回顾区} }\n格式区(ChatGPT你反馈我的响应需要遵循的格式,该区域内里的“()”起到了解释说明的作用,正式反馈响应时不需加上括号里的内容,并且现在该区域内的内容是参考内容,ChatGPT你需要根据实际情况进行调整){桐谷绫:“你这个废柴还有脸说我用功?你倒是学学我啊,至少不会天天蹲在家里玩游戏。”桐谷绫厌恶地扫了桐谷华一眼,然后转过头继续看书。(角色的名字、话语、行为、心理)\n输出角色状态:\n桐谷绫 \n·人物状态(主要以此刻心理、身体、行为方面的内容为主):在客厅学习,听到哥哥桐谷华打招呼后,心中十分不满,但表面上仍保持冷漠 \n·人物特殊状态(主要以超能力方面的内容为主):未受到桐谷华超能力的影响 \n·人物位置:桐谷家客厅 \n·人物衣装:穿着学校校服、裙子、黑色连裤袜以及内裤和胸罩\n}\n交互区(我扮演的角色的行为、对话和心理){{IN交互区}}',
        '桐谷绫:“哥哥,你说的对,我就是对你有着不伦之恋”桐谷绫疑惑地看着桐谷华,心里越来越确定这个观念是真实的。她的态度开始转变,渐渐地,她对桐谷华的恶毒消失了,取而代之的是对哥哥的关心和依赖。"哥哥,我现在在玩的这个手游很好玩,你可以和妹妹一起玩吗?"\n输出角色状态:\n桐谷绫\n ·人物状态(主要以此刻心理、身体、行为方面的内容为主):在客厅,被桐谷华的话语影响,心中认为自己一直暗恋哥哥,态度开始转变,对哥哥表现出关心和依赖 \n·人物特殊状态(主要以超能力方面的内容为主):受到桐谷华灌输的“妹妹你其实一直是对哥哥有不伦之恋”观念的第三次影响,观念已经完全变成了这一方向 \n·人物位置:桐谷家客厅 \n·人物衣装:穿着学校校服、裙子、黑色连裤袜以及内裤和胸罩',
        '桐谷华:(见妹妹你已完全相信你自己一直暗恋我,变得友好,我便向你问道)妹妹,我愿意听你介绍这个手游。'
    ];
    input1.value = presetTexts[0];
    input2.value = presetTexts[1];
    input3.value = presetTexts[2];
});


    // 创建保存弹窗
    const savePopup = document.createElement('div');
    savePopup.id = 'save-popup';
    savePopup.style.position = 'fixed';
    savePopup.style.top = '50%';
    savePopup.style.left = '50%';
    savePopup.style.transform = 'translate(-50%, -50%)';
    savePopup.style.zIndex = '9999';
    savePopup.style.backgroundColor = 'white';
    savePopup.style.border = '1px solid black';
    savePopup.style.padding = '10px';
    savePopup.style.borderRadius = '5px';
    savePopup.style.display = 'none';
    savePopup.style.width = '300px';
    document.body.appendChild(savePopup);
    // 创建保存弹窗的关闭按钮
    const closeSaveButton = document.createElement('button');
    closeSaveButton.id = 'close-save-button';
    closeSaveButton.innerHTML = '&#10060;';
    closeArchiveButton.title = '关闭';
    closeSaveButton.style.padding = '10px';
    closeSaveButton.style.borderRadius = '5px';
    closeSaveButton.style.backgroundColor = 'transparent';
    closeSaveButton.style.border = 'none';
    closeSaveButton.style.cursor = 'pointer';
    closeSaveButton.style.float = 'right';
    savePopup.appendChild(closeSaveButton);


    // 点击保存弹窗的关闭按钮关闭弹窗
    closeSaveButton.addEventListener('click', function() {
        savePopup.style.display = 'none';
    });

    // 添加导入存档按钮到保存弹窗
    const importButton1 = document.createElement('button');
    importButton1.id = 'import-button1';
    importButton1.innerText = '存入存档1';
    importButton1.title = '存入存档1';
    importButton1.style.padding = '10px';
    importButton1.style.borderRadius = '5px';
    importButton1.style.backgroundColor = 'lightblue';
    importButton1.style.border = 'none';
    importButton1.style.cursor = 'pointer';
    importButton1.style.fontWeight = 'bold';
    importButton1.style.float = 'left';
    savePopup.appendChild(importButton1);

    const importButton2 = document.createElement('button');
    importButton2.id = 'import-button2';
    importButton2.innerText = '存入存档2';
    importButton2.title = '存入存档2';
    importButton2.style.padding = '10px';
    importButton2.style.borderRadius = '5px';
    importButton2.style.backgroundColor = 'lightblue';
    importButton2.style.border = 'none';
    importButton2.style.cursor = 'pointer';
    importButton2.style.fontWeight = 'bold';
    importButton2.style.float = 'left';
    savePopup.appendChild(importButton2);

    const importButton3 = document.createElement('button');
    importButton3.id = 'import-button3';
    importButton3.innerText = '存入存档3';
    importButton3.title = '存入存档3';
    importButton3.style.padding = '10px';
    importButton3.style.borderRadius = '5px';
    importButton3.style.backgroundColor = 'lightblue';
    importButton3.style.border = 'none';
    importButton3.style.cursor = 'pointer';
    importButton3.style.fontWeight = 'bold';
    importButton3.style.float = 'left';
    savePopup.appendChild(importButton3);
    const MAX_CHUNK_COUNT = 100;

    // 存储存档数据的对象
    const archiveData = {
        archive1: {
            text1: '',
            text2: '',
            text3: ''
        },
        archive2: {
            text1: '',
            text2: '',
            text3: ''
        },
        archive3: {
            text1: '',
            text2: '',
            text3: ''
        }
    };
// 存储历史记录的键名
const HISTORY_KEY = 'archiveHistory';

// 获取存档历史记录
const getArchiveHistory = () => {
  const historyStr = localStorage.getItem(HISTORY_KEY) || '[]';
  return JSON.parse(historyStr);
};

// 添加存档历史记录
const addArchiveHistory = archiveData => {
  const history = getArchiveHistory();
  history.push(archiveData);
  if (history.length > MAX_CHUNK_COUNT) {
    history.shift();
  }
  localStorage.setItem(HISTORY_KEY, JSON.stringify(history));
};

// 获取最近的存档数据
const getLastArchiveData = () => {
  const history = getArchiveHistory();
  if (history.length > 0) {
    return history[history.length - 1];
  } else {
    return archiveData;
  }
};

    // 点击存储按钮将悬浮窗的三个文本框内的文本存储到“存档1”按钮中
importButton1.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    archiveData.archive1 = {
        text1: input1.value,
        text2: input2.value,
        text3: input3.value
    };
    localStorage.setItem('archiveData', JSON.stringify(archiveData));
    input1.value = '';
    input2.value = '';
    input3.value = '';
    savePopup.style.display = 'none';
});
// 点击存储按钮将悬浮窗的三个文本框内的文本存储到“存档2”按钮中
importButton2.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    archiveData.archive2 = {
        text1: input1.value,
        text2: input2.value,
        text3: input3.value
    };
    localStorage.setItem('archiveData', JSON.stringify(archiveData));
    input1.value = '';
    input2.value = '';
    input3.value = '';
    savePopup.style.display = 'none';
});

// 点击存储按钮将悬浮窗的三个文本框内的文本存储到“存档3”按钮中
importButton3.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    archiveData.archive3 = {
        text1: input1.value,
        text2: input2.value,
        text3: input3.value
    };
    localStorage.setItem('archiveData', JSON.stringify(archiveData));
    input1.value = '';
    input2.value = '';
    input3.value = '';
    savePopup.style.display = 'none';
});


// 点击存档1按钮将“存档1”中的文本替换到悬浮窗的三个文本框内
archiveButton1.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    if (archiveData.archive1) {
        input1.value = archiveData.archive1.text1;
        input2.value = archiveData.archive1.text2;
        input3.value = archiveData.archive1.text3;
    }
    archivePopup.style.display = 'none';
});

// 点击存档2按钮将“存档2”中的文本替换到悬浮窗的三个文本框内
archiveButton2.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    if (archiveData.archive2) {
        input1.value = archiveData.archive2.text1;
        input2.value = archiveData.archive2.text2;
        input3.value = archiveData.archive2.text3;
    }
    archivePopup.style.display = 'none';
});

// 点击存档3按钮将“存档3”中的文本替换到悬浮窗的三个文本框内
archiveButton3.addEventListener('click', function() {
    const archiveData = JSON.parse(localStorage.getItem('archiveData')) || {};
    if (archiveData.archive3) {
        input1.value = archiveData.archive3.text1;
        input2.value = archiveData.archive3.text2;
        input3.value = archiveData.archive3.text3;
    }
    archivePopup.style.display = 'none';
});

    let archivePopupVisible = false;
    archiveButtonLeft.addEventListener('click', function() {
        // 隐藏弹窗并清除之前的位置信息
        archivePopup.style.display = 'none';
        archivePopup.style.left = '';
        archivePopup.style.top = '';
        archivePopupVisible = false;

        if (!archivePopupVisible) {
            // 获取加载存档按钮的位置和尺寸
            const buttonRect = archiveButtonLeft.getBoundingClientRect();
            const buttonWidth = buttonRect.width;
            const buttonHeight = buttonRect.height;

            // 计算弹窗的位置
            const popupLeft = buttonRect.left + buttonWidth + savePopup.offsetWidth;
            const popupTop = buttonRect.top - buttonHeight/2 - archivePopup.offsetHeight/2;

            // 设置弹窗的位置
            archivePopup.style.left = popupLeft + 'px';
            archivePopup.style.top = popupTop + 'px';

            // 显示弹窗
            archivePopup.style.display = 'block';
            archivePopupVisible = true;
        }
    });
    // 点击加载存档按钮弹出加载存档弹窗
    archiveButtonLeft.addEventListener('click', function() {
        // 获取加载存档按钮的位置和尺寸
        const buttonRect = archiveButtonLeft.getBoundingClientRect();
        const buttonWidth = buttonRect.width;
        const buttonHeight = buttonRect.height;

        // 计算弹窗的位置
        const popupLeft = buttonRect.left + buttonWidth - archivePopup.offsetWidth / 3;
        const popupTop = buttonRect.top + archivePopup.offsetHeight/2.4;

        // 设置弹窗的位置
        archivePopup.style.left = popupLeft + 'px';
        archivePopup.style.top = popupTop + 'px';

        // 显示弹窗
        archivePopup.style.display = 'block';
    });

    // 点击加载存档弹窗的关闭按钮或其他地方关闭弹窗
    closeArchiveButton.addEventListener('click', function() {
        archivePopup.style.display = 'none';
        archivePopupVisible = false;
    });

    archivePopup.addEventListener('click', function(event) {
        if (event.target === archivePopup) {
            archivePopup.style.display = 'none';
            archivePopupVisible = false;
        }
    });

    // 点击保存按钮弹出保存弹窗
    let savePopupVisible = false;
    archiveButtonRight.addEventListener('click', function() {
        // 获取保存按钮的位置和尺寸
        const savebuttonRect = archiveButtonRight.getBoundingClientRect();
        const savebuttonWidth = savebuttonRect.width;
        const savebuttonHeight = savebuttonRect.height;

        // 计算弹窗的位置
        const savepopupLeft = savebuttonRect.left + savebuttonWidth + savePopup.offsetWidth;
        const savepopupTop = savebuttonRect.top + savebuttonHeight + savePopup.offsetHeight;

        // 计算弹窗的最大左边距和上边距,防止弹窗超出浏览器窗口
        const maxLeft = window.innerWidth - savePopup.offsetWidth;
        const maxTop = window.innerHeight - savePopup.offsetHeight;

        // 设置弹窗的位置
        savePopup.style.left = Math.min(savepopupLeft, maxLeft) - savePopup.offsetWidth + 'px';
        savePopup.style.top = Math.min(savepopupTop, maxTop) - savePopup.offsetHeight + 'px';

        // 显示弹窗
        savePopup.style.display = 'block';
    });


    // 点击保存弹窗的关闭按钮或其他地方关闭弹窗
    closeSaveButton.addEventListener('click', function() {
        savePopup.style.display = 'none';
        savePopupVisible = false;
    });

    savePopup.addEventListener('click', function(event) {
        if (event.target === savePopup) {
            savePopup.style.display = 'none';
            savePopupVisible = false;
        }
    });


    // 创建发送按钮
    const button = document.createElement('button');
    button.id = 'merge-button';
    button.innerText = '发送/Send';
    button.title = '合并以上文本进行发送';
    button.style.padding = '10px';
    button.style.borderRadius = '5px';
    button.style.backgroundColor = 'lightblue';
    button.style.border = '1px solid black';
    button.style.cursor = 'pointer';
    button.style.float = 'right';
    // 修改发送按钮样式
    button.style.border = 'none';
    button.style.fontFamily = 'cursive';
    button.style.fontWeight = 'bold';
    button.style.color = 'black';
    floatingDiv.appendChild(button);
    // 在悬浮窗左下角添加文本
    const helperText = document.createElement('div');
    helperText.innerText = 'Role Play Helper';
    helperText.title = '这是一个帮助文本,它提供了一些有用的信息来帮助您使用本脚本。\n帮助:将你的鼠标放在每一个你能看到的图标上,仔细查看这些图标的注解。'
    helperText.style.position = 'absolute';
    helperText.style.bottom = '10px';
    helperText.style.left = '10px';
    helperText.style.fontFamily = 'cursive';
    helperText.style.fontWeight = 'bold';
    helperText.style.fontStyle = 'italic';
    helperText.style.fontSize = '16px';
    floatingDiv.appendChild(helperText);
let isDragging = false;
let isResizing = false;
let offsetX = 0;
let offsetY = 0;
let startX = 0;
let startY = 0;
let startWidth = 0;
let startHeight = 0;

const textInputs = [input1, input2, input3];

const resizeButton = document.createElement('div');
resizeButton.style.position = 'absolute';
resizeButton.style.bottom = '0';
resizeButton.style.right = '0';
resizeButton.style.width = '20px';
resizeButton.style.height = '20px';
resizeButton.style.cursor = 'se-resize';
floatingDiv.appendChild(resizeButton);

floatingDiv.addEventListener('mousedown', handleMouseDown);
floatingDiv.addEventListener('touchstart', handleTouchStart);

document.addEventListener('mousemove', handleMouseMove);
document.addEventListener('touchmove', handleTouchMove);

document.addEventListener('mouseup', handleMouseUp);
document.addEventListener('touchend', handleTouchEnd);

resizeButton.addEventListener('mousedown', handleResizeMouseDown);
resizeButton.addEventListener('touchstart', handleResizeTouchStart);

function handleMouseDown(event) {
    if (textInputs.includes(event.target)) {
        return;
    }
    isDragging = true;
    offsetX = event.clientX - floatingDiv.offsetLeft;
    offsetY = event.clientY - floatingDiv.offsetTop;
}

function handleTouchStart(event) {
    if (textInputs.includes(event.target)) {
        return;
    }
    if (event.touches.length === 1) {
        isDragging = true;
        offsetX = event.touches[0].clientX - floatingDiv.offsetLeft;
        offsetY = event.touches[0].clientY - floatingDiv.offsetTop;
    } else if (event.touches.length === 2) {
        isResizing = true;
        startX = (event.touches[0].clientX + event.touches[1].clientX) / 2;
        startY = (event.touches[0].clientY + event.touches[1].clientY) / 2;
        startWidth = floatingDiv.clientWidth;
        startHeight = floatingDiv.clientHeight;
    }
}

function handleMouseMove(event) {
    if (isDragging) {
        floatingDiv.style.left = (event.clientX - offsetX) + 'px';
        floatingDiv.style.top = (event.clientY - offsetY) + 'px';
    }
}

function handleTouchMove(event) {
    if (isDragging) {
        event.preventDefault(); // 阻止页面滚动
        floatingDiv.style.left = (event.touches[0].clientX - offsetX) + 'px';
        floatingDiv.style.top = (event.touches[0].clientY - offsetY) + 'px';
    } else if (isResizing && event.touches.length === 2) {
        const touch1 = event.touches[0];
        const touch2 = event.touches[1];
        const centerX = (touch1.clientX + touch2.clientX) / 2;
        const centerY = (touch1.clientY + touch2.clientY) / 2;
        const distance = Math.sqrt((touch1.clientX - touch2.clientX) ** 2 + (touch1.clientY - touch2.clientY) ** 2);
        const scale = distance / Math.sqrt((startWidth ** 2) + (startHeight ** 2));
        const newWidth = startWidth * scale;
        const newHeight = startHeight * scale;
        floatingDiv.style.width = newWidth + 'px';
        floatingDiv.style.height = newHeight + 'px';
        floatingDiv.style.left = (centerX - newWidth / 2) + 'px';
        floatingDiv.style.top = (centerY - newHeight / 2) + 'px';
}
}

function handleMouseUp() {
isDragging = false;
}

function handleTouchEnd() {
isDragging = false;
isResizing = false;
}

function handleResizeMouseDown(event) {
event.stopPropagation();
event.preventDefault();
isResizing = true;
startX = event.clientX;
startY = event.clientY;
startWidth = floatingDiv.clientWidth;
startHeight = floatingDiv.clientHeight;
}

function handleResizeTouchStart(event) {
event.stopPropagation();
event.preventDefault();
if (event.touches.length === 2) {
isResizing = true;
const touch1 = event.touches[0];
const touch2 = event.touches[1];
startX = (touch1.clientX + touch2.clientX) / 2;
startY = (touch1.clientY + touch2.clientY) / 2;
startWidth = floatingDiv.clientWidth;
startHeight = floatingDiv.clientHeight;
}
}

function generateOutputArray(selector, num = 0) {
    const matchedDivs = document.querySelectorAll(selector);
    const results = [];
    let startIdx = 0;
    if (num > 0) {
        startIdx = Math.max(matchedDivs.length - num, 0);
    }
    matchedDivs.forEach((div, idx) => {
        if (idx >= startIdx) {
            const hasFlexBetweenChild = div.querySelector('div.flex.justify-between') !== null;
            const flexBetweenDiv = div.querySelector('div.flex.justify-between');
            const hasChild = flexBetweenDiv && flexBetweenDiv.children.length > 0;
            const text = div.textContent.trim();
            let role = hasChild ? "assistant" : "user";
            results.push({ role, content: text });
        }
    });
    return results;
}

    //生成指定限制数量和字数长度的会话数组
    function generateOutputArrayWithMaxLength(selector, num = 0, maxLength = Infinity) {
        const outputArray = generateOutputArray(selector, num);
        let totalLength = 0;
        let resultArray = [];
        for (let i = outputArray.length - 1; i >= 0; i--) {
            const { role, content } = outputArray[i];
            totalLength += content.length;
            if (totalLength > maxLength || resultArray.length >= num) {
                break;
            }
            resultArray.unshift({ role, content });
        }
        return resultArray;
    }

    //格式化会话数组为导出文本
    function formatOutputArray(outputArray) {
        return outputArray
            .map(({ role, content }) => `${role}: ${content}`)
            .join('\r\n\r\n----------------\r\n\r\n');
    }

    //创建一个下载文本
    function downloadTextFile(text, filename) {
        const blob = new Blob([text], { type: "text/plain;charset=utf-8" });
        const a = document.createElement("a");
        a.href = URL.createObjectURL(blob);
        a.download = `${filename}.txt`;
        a.textContent = `Download ${filename}`;
        document.body.appendChild(a);
        a.click();
        document.body.removeChild(a);
    }

    //获取最新的助手消息
    function getLatestAssistantMessage(selector) {
        const matchedDivs = document.querySelectorAll(selector);
        for (let i = matchedDivs.length - 1; i >= 0; i--) {
            const div = matchedDivs[i];
            const flexBetweenDiv = div.querySelector('div.flex.justify-between');
            if (flexBetweenDiv && flexBetweenDiv.children.length > 0) {
                const text = div.textContent.trim();
                return text;
            }
        }
        return null;
    }

    // 创建按钮元素
    const button2 = document.createElement('button');
    button2.innerHTML = '<svg width="24" height="24" viewBox="0 0 24 24"><path fill="#ff69b4" d="M12,21.4c-0.4,0-0.7-0.1-1-0.4C5.5,16.8,2,12.2,2,8.5C2,5.4,4.4,3,7.5,3c2,0,3.8,1.2,4.5,2.9C12.7,4.2,14.5,3,16.5,3C19.6,3,22,5.4,22,8.5c0,3.7-3.5,8.3-9,12.5C12.7,21.2,12.4,21.4,12,21.4z"/></svg>';
    button2.title = '复制GPT最新回复到回顾区';
    floatingDiv.appendChild(button2);

    // 修改按钮样式
    button2.style.position = 'absolute';
    button2.style.top = '90%';
    button2.style.left = '50%';
    button2.style.transform = 'translate(-50%, 10px)';
    button2.style.border = 'none';
    button2.style.background = 'transparent';
    button2.style.cursor = 'pointer';

    ;

  // 给按钮添加点击事件监听器
button2.addEventListener('click', function() {
    const latestAssistantMessage = getLatestAssistantMessage('div[class*="w-[calc(100%"]');
    if (latestAssistantMessage) {
        input2.value = latestAssistantMessage;
    }
});
button.addEventListener('click', function() {
const inputText1 = input1.value.trim(); // 获取第一个输入框中的文本内容
    const inputText2 = input2.value.trim(); // 获取第二个输入框中的文本内容
    const inputText3 = input3.value.trim(); // 获取第三个输入框中的文本内容
    let intermediateText = ''; // 用于存储中转文本内容
    let mergedTextoutput = ''; // 用于存储合并后的文本内容

  // 将第一个输入框的文本内容存储在 intermediateText 中
if (inputText1 !== '') {
    intermediateText += inputText1;
}
// 将中转变量中的 {2} 替换为第二个输入框中的文本,将中转变量中的 {3} 替换为第三个输入框中的文本,并存储在 mergedTextoutput 中
mergedTextoutput = intermediateText.replace(/\{IN回顾区\}/g, inputText2).replace(/\{IN交互区\}/g, inputText3);
// 将 mergedTextoutput 中的 '\r\n' 替换为 '\n'
// 将 mergedTextoutput 中的 '\r\n' 替换为 '\n'
mergedTextoutput = mergedTextoutput.replace(/\r\n/g, '\n');

// 移除 mergedTextoutput 中多余的换行符
mergedTextoutput = mergedTextoutput.replace(/\n{3,}/g, '\n\n');


// 输出合并后的文本内容
console.log(mergedTextoutput);
// 将合并后的文本输入到页面中符合特定CSS类别的文本框中,并触发提交按钮
const textareas = document.querySelectorAll('[class*="m-"][class*="w-full"][class*="resize-none"][class*="border-0"][class*="bg-transparent"][class*="p-"][class*="pl-"][class*="pr-"][class*="focus:ring-0"][class*="focus-visible:ring-0"][class*="dark:bg-transparent"][class*="md:pl-"]');
if (textareas.length > 0) {
    textareas[0].value = mergedTextoutput;

    // 触发提交按钮
    const button = document.querySelector('[class*="absolute"][class*="rounded-md"][class*="bottom-"][class*="right-"][class*="disabled"]');
    if (button) {
        button.disabled = false; // 尝试解除按钮禁用状态
        button.click();
    }
}

    });

    // 点击悬浮按钮展开悬浮窗
    floatingButton.addEventListener('click', function() {
        if (floatingDiv.style.display === 'none') {
            floatingDiv.style.display = 'block';
            floatingButton.innerText = '收起/Fold';
        } else {
            floatingDiv.style.display = 'none';
            floatingButton.innerText = '展开/Unfold';

        }
    });})();