您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Various Tools for ChatGPT
当前为
// ==UserScript== // @name ChatGPT Tools // @namespace http://tampermonkey.net/ // @version 1.7 // @description Various Tools for ChatGPT // @author You // @match https://chatgpt.com/* // @grant GM_addStyle // ==/UserScript== (function () { 'use strict'; // =============================================================== MAIN INJECT =============================================================== function isMobileDevice() { return /Mobi|Android/i.test(navigator.userAgent); } if (!isMobileDevice()) { function disableEnterKey(event) { // Check if the Enter key is pressed if (event.key === "Enter") { // Allow Shift + Enter for a new paragraph if (event.shiftKey) { console.log("New paragraph created."); return; // Exit the function, allowing the default behavior } // Prevent default Enter key behavior event.preventDefault(); console.log("Enter key functionality disabled."); const inputPanelGPT = document.querySelector('div#prompt-textarea.ProseMirror'); // RULES const getRulesState = localStorage.getItem('enableRules'); if (getRulesState === "true") { const getSelectedRuleValue = localStorage.getItem('selectedRuleValue'); const newParagraph = document.createElement('p'); newParagraph.textContent = getSelectedRuleValue; inputPanelGPT.appendChild(newParagraph); console.log('Next Rule appended:', getSelectedRuleValue); } // Update the selection range to the end of the container const selection = window.getSelection(); selection.removeAllRanges(); const newRange = document.createRange(); newRange.selectNodeContents(inputPanelGPT); newRange.collapse(false); selection.addRange(newRange); const inputEvent = new Event('input', { bubbles: true, cancelable: true }); inputPanelGPT.dispatchEvent(inputEvent); setTimeout(() => { const sendButton = document.querySelector('button[data-testid="send-button"]'); if (sendButton) { sendButton.click(); console.log('Send button clicked after delay.'); } else { console.error('Send button not found.'); } }, 100); // 10ms delay (adjust as needed) } } // Attach the event listener to the document document.addEventListener("keydown", disableEnterKey, true); } if (isMobileDevice()) { let programmaticClick = false; // Flag to differentiate between user and programmatic clicks document.body.addEventListener('click', function (event) { const sendButton1 = document.querySelector('button[aria-label="Send prompt"]'); // Check if the button exists and if the clicked target is the send button if (sendButton1 && sendButton1.contains(event.target)) { console.error('AAAAAAA'); // If this is a programmatic click, bypass the custom logic if (programmaticClick) { programmaticClick = false; // Reset the flag for subsequent clicks console.log("Programmatic click detected, skipping custom logic."); return; } // Prevent default click behavior and propagation temporarily event.preventDefault(); event.stopImmediatePropagation(); console.log("Send Button functionality temporarily disabled to execute custom logic."); const inputPanelGPT = document.querySelector('div#prompt-textarea.ProseMirror'); // RULES const getRulesState = localStorage.getItem('enableRules'); if (getRulesState === "true") { const getSelectedRuleValue = localStorage.getItem('selectedRuleValue'); // Check if the rule is already appended const existingRule = Array.from(inputPanelGPT.children).find( child => child.textContent === getSelectedRuleValue ); if (!existingRule) { const newParagraph = document.createElement('p'); newParagraph.textContent = getSelectedRuleValue; inputPanelGPT.appendChild(newParagraph); console.log('Next Rule appended:', getSelectedRuleValue); } else { console.log('Rule already exists, not appending again.'); } } // Update the selection range to the end of the container const selection = window.getSelection(); selection.removeAllRanges(); const newRange = document.createRange(); newRange.selectNodeContents(inputPanelGPT); newRange.collapse(false); selection.addRange(newRange); const inputEvent = new Event('input', { bubbles: true, cancelable: true }); inputPanelGPT.dispatchEvent(inputEvent); // Restore the send functionality after custom logic setTimeout(() => { console.log("Restoring Send Button functionality."); programmaticClick = true; // Set the flag to indicate programmatic click sendButton1.click(); // Programmatically trigger the send action }, 20); // Use a 0ms delay to allow custom logic to finish } }); } // ================================================================ GLOBAL STYLES ================================================================= const CONFIG = { panelBackground: '#171717', // PanelButtons BUTTON_HIGHLIGHT: '#424242', BUTTON_OUTLINE: '1px solid #4E4E4E', }; // Black Background Overlay const overlay = document.createElement('div'); overlay.style.position = 'fixed'; overlay.style.top = '0'; overlay.style.left = '0'; overlay.style.width = '100%'; overlay.style.height = '100%'; overlay.style.backgroundColor = 'rgba(0,0,0,0.5)'; overlay.style.zIndex = '999'; overlay.style.display = 'none'; function showOverlay() { document.body.appendChild(overlay); overlay.style.display = 'block'; } function hideOverlay() { overlay.style.display = 'none'; } // ================================================================= MAIN PANEL ================================================================== function mainPanelScript() { // Create and add the arrow button to open the storage panel const arrowButton = document.createElement('div'); arrowButton.innerHTML = '〈'; arrowButton.style.position = 'fixed'; arrowButton.style.bottom = '50%'; arrowButton.style.right = '0'; arrowButton.style.padding = '10px'; arrowButton.style.fontSize = '24px'; arrowButton.style.zIndex = '998'; arrowButton.style.cursor = 'pointer'; arrowButton.style.color = '#B4B4B4'; arrowButton.style.borderRadius = '5px 0 0 5px'; arrowButton.style.transition = 'transform 0.3s ease, right 0.3s ease'; // Making Panel available for the whole script window.mainPanel = document.createElement('div'); mainPanel.style.position = 'fixed'; mainPanel.style.top = '0'; mainPanel.style.right = '-250px'; // Initially hidden mainPanel.style.height = '100%'; mainPanel.style.width = '250px'; mainPanel.style.backgroundColor = CONFIG.panelBackground; mainPanel.style.transition = 'right 0.3s ease'; mainPanel.style.zIndex = '999'; // Create the header above the button const mainPanelHeader = document.createElement('div'); mainPanelHeader.innerText = 'ChatGPT Tools'; mainPanelHeader.style.margin = '20px'; mainPanelHeader.style.padding = '10px'; mainPanelHeader.style.fontSize = '19px'; mainPanelHeader.style.fontWeight = '550'; mainPanelHeader.style.color = '#ECECEC'; mainPanelHeader.style.textAlign = 'center'; // Create the background overlay window.mainPanelOverlay = document.createElement('div'); mainPanelOverlay.style.position = 'fixed'; mainPanelOverlay.style.top = '0'; mainPanelOverlay.style.left = '0'; mainPanelOverlay.style.width = '100%'; mainPanelOverlay.style.height = '100%'; mainPanelOverlay.style.backgroundColor = 'rgba(0, 0, 0, 0.0)'; mainPanelOverlay.style.zIndex = '997'; mainPanelOverlay.style.display = 'none'; // Initially hidden // Toggle panel visibility arrowButton.addEventListener('click', () => { if (mainPanel.style.right === '-250px') { mainPanel.style.right = '0'; arrowButton.style.right = '250px'; arrowButton.style.transform = 'rotate(180deg)'; mainPanelOverlay.style.display = 'block'; // Show overlay } else { closePanel(); } }); // Close panel and remove overlay mainPanelOverlay.addEventListener('click', () => { closePanel(); }); function closePanel() { mainPanel.style.right = '-250px'; arrowButton.style.right = '0'; arrowButton.style.transform = 'rotate(0deg)'; mainPanelOverlay.style.display = 'none'; // Hide overlay } document.body.appendChild(arrowButton); document.body.appendChild(mainPanelOverlay); document.body.appendChild(mainPanel); mainPanel.appendChild(mainPanelHeader); } // ==================================================================== RULES ==================================================================== function rulesScript() { // Profiles object structure: { profileName: [arrayOfRules], ... } let profiles = {}; let currentProfile = null; let customRules = []; let currentIndex = 0; // Load profiles from localStorage const storedRulesProfiles = localStorage.getItem('rulesProfiles'); if (storedRulesProfiles) { profiles = JSON.parse(storedRulesProfiles); } // Check if there's a previously selected profile stored const selectedProfileRules = localStorage.getItem('selectedProfile.Rules'); if (Object.keys(profiles).length === 0) { // If no profiles exist, create a default one profiles['Default'] = []; saveProfiles(); currentProfile = 'Default'; } else { // If we have a stored selected profile, use that; otherwise use first available if (selectedProfileRules && profiles[selectedProfileRules]) { currentProfile = selectedProfileRules; } else { currentProfile = Object.keys(profiles)[0]; } } // Sync customRules with currently selected profile loadProfileRules(currentProfile); function loadProfileRules(profileName) { currentProfile = profileName; customRules = profiles[currentProfile] || []; // Save the selected profile so it's sticky across sessions localStorage.setItem('selectedProfile.Rules', currentProfile); } function saveProfiles() { localStorage.setItem('rulesProfiles', JSON.stringify(profiles)); } // Create Button and Panel UI for Local Storage Key Management window.manageRulesButton = document.createElement('div'); window.manageRulesButton.innerHTML = ` <button id="toggle-rules-panel" style=" position: relative; top: 10px; right: 0px; left: 10px; padding: 7px 15px; background: transparent; color: #b0b0b0; border: none; border-radius: 8px; font-size: 16px; text-align: left; cursor: pointer; width: 90%; display: flex; align-items: center; gap: 10px; transition: background-color 0.1s, color 0.1s; z-index: 1001;"> <svg fill="#B0B0B0" version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16px" height="16px" viewBox="0 0 492.508 492.508" xml:space="preserve" style="padding-right: 0px; margin-left: 1px;"> <g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_iconCarrier"> <g> <g> <path d="M199.493,402.145c0-10.141-8.221-18.361-18.36-18.361H42.475c-10.139,0-18.36,8.221-18.36,18.361 c0,3.195,0.818,6.199,2.255,8.816H0v38.067h223.607v-38.067h-26.369C198.674,408.343,199.493,405.34,199.493,402.145z"> </path> <path d="M175.898,88.224l117.157,74.396c9.111,4.643,20.43,1.678,26.021-7.129l5.622-8.85 c5.938-9.354,3.171-21.75-6.182-27.69L204.592,46.608c-9.352-5.939-21.748-3.172-27.688,6.182l-5.622,8.851 C165.692,70.447,167.82,81.952,175.898,88.224z"> </path> <path d="M492.456,372.433l-0.082-1.771l-0.146-1.672c-0.075-1.143-0.235-2.159-0.375-3.204c-0.562-4.177-1.521-7.731-2.693-10.946 c-2.377-6.386-5.738-11.222-9.866-14.845c-1.027-0.913-2.126-1.714-3.218-2.528l-3.271-2.443 c-2.172-1.643-4.387-3.218-6.587-4.815c-2.196-1.606-4.419-3.169-6.644-4.729c-2.218-1.571-4.445-3.125-6.691-4.651 c-4.468-3.089-8.983-6.101-13.51-9.103l-6.812-4.464l-6.85-4.405c-4.58-2.911-9.167-5.813-13.785-8.667 c-4.611-2.865-9.24-5.703-13.896-8.496l-13.979-8.363l-14.072-8.22l-14.149-8.096l-14.219-7.987l-14.287-7.882l-14.354-7.773 c-4.802-2.566-9.599-5.137-14.433-7.653c-4.822-2.529-9.641-5.071-14.498-7.548l-4.398,6.928l-22.17-10.449l24.781-39.026 l-117.156-74.395l-60.944,95.974l117.157,74.395l24.781-39.026l18.887,15.622l-4.399,6.929c4.309,3.343,8.657,6.619,12.998,9.91 c4.331,3.305,8.698,6.553,13.062,9.808l13.14,9.686l13.211,9.577l13.275,9.474l13.346,9.361l13.422,9.242l13.514,9.095 c4.51,3.026,9.045,6.009,13.602,8.964c4.547,2.967,9.123,5.882,13.707,8.792l6.898,4.324l6.936,4.266 c4.643,2.818,9.289,5.625,13.985,8.357c2.337,1.383,4.689,2.739,7.055,4.078c2.358,1.349,4.719,2.697,7.106,4 c2.383,1.312,4.75,2.646,7.159,3.912l3.603,1.922c1.201,0.64,2.394,1.296,3.657,1.837c5.036,2.194,10.841,3.18,17.63,2.614 c3.409-0.305,7.034-0.949,11.054-2.216c1.006-0.317,1.992-0.606,3.061-1.023l1.574-0.58l1.639-0.68 c2.185-0.91,4.523-2.063,7.059-3.522C492.513,377.405,492.561,374.799,492.456,372.433z"> </path> <path d="M67.897,261.877l113.922,72.341c9.354,5.938,21.75,3.172,27.689-6.181l5.621-8.852 c5.592-8.808,3.462-20.311-4.615-26.583L93.358,218.207c-9.111-4.642-20.43-1.678-26.022,7.13l-5.62,8.85 C55.775,243.541,58.543,255.938,67.897,261.877z"> </path> </g> </g> </g> </svg> Manage Rules </button> `; const rulesButtonElement = manageRulesButton.querySelector('button'); rulesButtonElement.onmouseover = () => { rulesButtonElement.style.backgroundColor = '#212121'; rulesButtonElement.style.color = '#ffffff'; }; rulesButtonElement.onmouseout = () => { rulesButtonElement.style.backgroundColor = 'transparent'; rulesButtonElement.style.color = '#b0b0b0'; }; const rulesPanel = document.createElement('div'); rulesPanel.style.position = 'fixed'; rulesPanel.style.top = '50%'; rulesPanel.style.left = '50%'; rulesPanel.style.transform = 'translate(-50%, -50%)'; rulesPanel.style.zIndex = 1000; rulesPanel.style.backgroundColor = '#2f2f2f'; rulesPanel.style.padding = '20px'; rulesPanel.style.borderRadius = '20px'; rulesPanel.style.display = 'none'; document.body.appendChild(rulesPanel); const isMobile = () => window.innerWidth <= 768; const rulesTitle = document.createElement('h2'); rulesTitle.innerText = 'Manage Rules'; rulesTitle.style.textAlign = 'center'; rulesTitle.style.color = '#ffffff'; rulesTitle.style.fontSize = '24px'; rulesTitle.style.fontWeight = '550'; rulesTitle.style.marginBottom = '20px'; rulesPanel.appendChild(rulesTitle); const rulesCloseButton = document.createElement('button'); rulesCloseButton.style.position = 'absolute'; rulesCloseButton.style.borderRadius = '50%'; rulesCloseButton.style.top = '20px'; rulesCloseButton.style.right = '20px'; rulesCloseButton.style.backgroundColor = 'transparent'; rulesCloseButton.style.cursor = 'pointer'; rulesCloseButton.style.width = '32px'; rulesCloseButton.style.height = '32px'; rulesCloseButton.style.display = 'flex'; rulesCloseButton.style.alignItems = 'center'; rulesCloseButton.style.justifyContent = 'center'; const rulesCloseSymbol = document.createElement('span'); rulesCloseSymbol.innerText = '✕'; rulesCloseSymbol.style.color = '#FBFBFE'; rulesCloseSymbol.style.fontSize = '14px'; rulesCloseSymbol.style.fontWeight = '550'; rulesCloseSymbol.style.transform = 'translateY(-1px) translateX(0.4px)'; rulesCloseButton.appendChild(rulesCloseSymbol); rulesCloseButton.addEventListener('mouseenter', () => { rulesCloseButton.style.backgroundColor = '#676767'; }); rulesCloseButton.addEventListener('mouseleave', () => { rulesCloseButton.style.backgroundColor = 'transparent'; }); const closeRulesPanel = () => { rulesPanel.style.display = 'none'; hideOverlay(); }; rulesCloseButton.addEventListener('click', closeRulesPanel); rulesPanel.appendChild(rulesCloseButton); const container = document.createElement('div'); container.style.display = 'flex'; container.style.height = 'calc(100% - 60px)'; container.style.gap = '20px'; rulesPanel.appendChild(container); // Mobile: show/hide profile panel functionality const profilesOverlay = document.createElement('div'); profilesOverlay.style.position = 'absolute'; profilesOverlay.style.top = '0'; profilesOverlay.style.left = '0'; profilesOverlay.style.width = '100%'; profilesOverlay.style.height = '100%'; profilesOverlay.style.backgroundColor = '#2f2f2f'; profilesOverlay.style.padding = '20px'; profilesOverlay.style.display = 'none'; profilesOverlay.style.zIndex = 1100; profilesOverlay.style.borderRadius = '20px'; profilesOverlay.style.flexDirection = 'column'; profilesOverlay.style.overflowY = 'auto'; rulesPanel.appendChild(profilesOverlay); const profilesTitleOverlay = document.createElement('h3'); profilesTitleOverlay.innerText = 'Profiles'; profilesTitleOverlay.style.color = '#ffffff'; profilesTitleOverlay.style.textAlign = 'center'; profilesOverlay.appendChild(profilesTitleOverlay); const profilesCloseOverlay = document.createElement('button'); profilesCloseOverlay.innerText = 'Close'; profilesCloseOverlay.style.margin = '10px auto'; profilesCloseOverlay.style.display = 'block'; profilesCloseOverlay.style.padding = '10px'; profilesCloseOverlay.style.width = '90%'; profilesCloseOverlay.style.backgroundColor = 'transparent'; profilesCloseOverlay.style.color = '#ffffff'; profilesCloseOverlay.style.border = '1px solid #444'; profilesCloseOverlay.style.borderRadius = '50px'; profilesCloseOverlay.style.cursor = 'pointer'; profilesCloseOverlay.addEventListener('mouseenter', () => { profilesCloseOverlay.style.backgroundColor = CONFIG.BUTTON_HIGHLIGHT; }); profilesCloseOverlay.addEventListener('mouseleave', () => { profilesCloseOverlay.style.backgroundColor = 'transparent'; }); profilesCloseOverlay.addEventListener('click', () => { profilesOverlay.style.display = 'none'; }); profilesOverlay.appendChild(profilesCloseOverlay); const profilesListOverlay = document.createElement('div'); profilesListOverlay.style.flex = '1'; profilesListOverlay.style.overflowY = 'auto'; profilesOverlay.appendChild(profilesListOverlay); const addProfileButtonOverlay = document.createElement('button'); addProfileButtonOverlay.textContent = 'Add Profile'; addProfileButtonOverlay.style.margin = '10px auto'; addProfileButtonOverlay.style.display = 'block'; addProfileButtonOverlay.style.padding = '10px'; addProfileButtonOverlay.style.border = CONFIG.BUTTON_OUTLINE; addProfileButtonOverlay.style.width = '90%'; addProfileButtonOverlay.style.backgroundColor = 'transparent'; addProfileButtonOverlay.style.borderRadius = '50px'; addProfileButtonOverlay.style.cursor = 'pointer'; addProfileButtonOverlay.addEventListener('mouseenter', () => { addProfileButtonOverlay.style.backgroundColor = CONFIG.BUTTON_HIGHLIGHT; }); addProfileButtonOverlay.addEventListener('mouseleave', () => { addProfileButtonOverlay.style.backgroundColor = 'transparent'; }); addProfileButtonOverlay.addEventListener('click', () => { const newProfileName = prompt('Enter Profile Name:'); if (newProfileName && !profiles[newProfileName]) { profiles[newProfileName] = []; saveProfiles(); renderProfilesList(); } }); profilesOverlay.appendChild(addProfileButtonOverlay); // Left side (profiles) const profilesContainer = document.createElement('div'); profilesContainer.style.width = '250px'; // profilesContainer.style.backgroundColor = '#1E1E1E'; profilesContainer.style.borderRight = '1px solid #444444'; // Added border width, style, and color profilesContainer.style.display = 'flex'; profilesContainer.style.flexDirection = 'column'; profilesContainer.style.marginTop = '-4.7%'; profilesContainer.style.padding = '10px'; profilesContainer.style.overflowY = 'auto'; const profilesTitle = document.createElement('h3'); profilesTitle.innerText = 'Profiles'; profilesTitle.style.color = '#ffffff'; profilesTitle.style.textAlign = 'center'; profilesContainer.appendChild(profilesTitle); const profilesList = document.createElement('div'); profilesList.style.flex = '1'; profilesList.style.overflowY = 'auto'; profilesContainer.appendChild(profilesList); const addProfileButton = document.createElement('button'); addProfileButton.textContent = 'Add Profile'; addProfileButton.style.margin = '10px auto'; addProfileButton.style.display = 'block'; addProfileButton.style.padding = '10px'; addProfileButton.style.border = CONFIG.BUTTON_OUTLINE; addProfileButton.style.width = '90%'; addProfileButton.style.backgroundColor = 'transparent'; addProfileButton.style.borderRadius = '50px'; addProfileButton.style.cursor = 'pointer'; addProfileButton.addEventListener('mouseenter', () => { addProfileButton.style.backgroundColor = CONFIG.BUTTON_HIGHLIGHT; }); addProfileButton.addEventListener('mouseleave', () => { addProfileButton.style.backgroundColor = 'transparent'; }); addProfileButton.addEventListener('click', () => { const newProfileName = prompt('Enter Profile Name:'); if (newProfileName && !profiles[newProfileName]) { profiles[newProfileName] = []; saveProfiles(); renderProfilesList(); } }); profilesContainer.appendChild(addProfileButton); // A button to toggle profiles overlay in mobile view const toggleProfilesButton = document.createElement('button'); toggleProfilesButton.innerText = 'Show Profiles'; toggleProfilesButton.style.display = 'none'; toggleProfilesButton.style.margin = '10px auto'; toggleProfilesButton.style.padding = '10px'; toggleProfilesButton.style.border = 'none'; toggleProfilesButton.style.width = '90%'; toggleProfilesButton.style.border = CONFIG.BUTTON_OUTLINE; toggleProfilesButton.style.backgroundColor = 'transparent'; toggleProfilesButton.style.borderRadius = '50px'; toggleProfilesButton.style.cursor = 'pointer'; toggleProfilesButton.addEventListener('mouseenter', () => { toggleProfilesButton.style.backgroundColor = CONFIG.BUTTON_HIGHLIGHT; }); toggleProfilesButton.addEventListener('mouseleave', () => { toggleProfilesButton.style.backgroundColor = 'transparent'; }); toggleProfilesButton.addEventListener('click', () => { profilesOverlay.style.display = 'flex'; renderProfilesList(); // Update list in overlay }); rulesPanel.insertBefore(toggleProfilesButton, container); function renderProfilesList() { // Decide whether to render in overlay or side panel const targetList = isMobile() ? profilesListOverlay : profilesList; targetList.innerHTML = ''; Object.keys(profiles).forEach(profileName => { const profileItem = document.createElement('div'); profileItem.style.display = 'flex'; profileItem.style.justifyContent = 'space-between'; profileItem.style.alignItems = 'center'; profileItem.style.backgroundColor = profileName === currentProfile ? '#424242' : 'transparent'; profileItem.style.color = '#ffffff'; profileItem.style.padding = '5px 10px'; profileItem.style.borderRadius = '5px'; profileItem.style.marginBottom = '5px'; profileItem.style.cursor = 'pointer'; const nameSpan = document.createElement('span'); nameSpan.innerText = profileName; nameSpan.style.flex = '1'; profileItem.appendChild(nameSpan); profileItem.addEventListener('click', () => { loadProfileRules(profileName); if (isMobile()) { profilesOverlay.style.display = 'none'; } renderProfilesList(); renderPanel(); }); // Delete button for the profile if (profileName !== 'Default') { const deleteButton = document.createElement('button'); deleteButton.style.cssText = 'color: #B4B4B4; background-color: transparent; cursor: pointer;'; deleteButton.innerHTML = ` <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"> <path fill-rule="evenodd" clip-rule="evenodd" d=" M10.5555 4 C10.099 4 9.70052 4.30906 9.58693 4.75114 L9.29382 5.8919 H14.715 L14.4219 4.75114 C14.3083 4.30906 13.9098 4 13.4533 4H10.5555 M16.7799 5.8919 L16.3589 4.25342 C16.0182 2.92719 14.8226 2 13.4533 2H10.5555 C9.18616 2 7.99062 2.92719 7.64985 4.25342 L7.22886 5.8919 H4 C3.44772 5.8919 3 6.33961 3 6.8919 C3 7.44418 3.44772 7.8919 4 7.8919H4.10069 L5.31544 19.3172 C5.47763 20.8427 6.76455 22 8.29863 22H15.7014 C17.2354 22 18.5224 20.8427 18.6846 19.3172 L19.8993 7.8919 H20 C20.5523 7.8919 21 7.44418 21 6.8919 C21 6.33961 20.5523 5.8919 20 5.8919H16.7799 M17.888 7.8919 H6.11196 L7.30423 19.1057 C7.3583 19.6142 7.78727 20 8.29863 20H15.7014 C16.2127 20 16.6417 19.6142 16.6958 19.1057 L17.888 7.8919 M10 10 C10.5523 10 11 10.4477 11 11V16 C11 16.5523 10.5523 17 10 17 C9.44772 17 9 16.5523 9 16V11 C9 10.4477 9.44772 10 10 10 M14 10 C14.5523 10 15 10.4477 15 11V16 C15 16.5523 14.5523 17 14 17 C13.4477 17 13 16.5523 13 16V11 C13 10.4477 13.4477 10 14 10 " fill="currentColor"/> </svg> `; deleteButton.addEventListener('mouseover', () => { deleteButton.style.color = '#E3E3E3'; }); deleteButton.addEventListener('mouseout', () => { deleteButton.style.color = '#B4B4B4'; }); deleteButton.addEventListener('click', (event) => { event.stopPropagation(); if (confirm(`Delete profile "${profileName}"?`)) { delete profiles[profileName]; if (currentProfile === profileName) { currentProfile = Object.keys(profiles)[0]; loadProfileRules(currentProfile); } saveProfiles(); renderProfilesList(); renderPanel(); } }); profileItem.appendChild(deleteButton); } targetList.appendChild(profileItem); }); } // Right side rules management const rightSideContainer = document.createElement('div'); rightSideContainer.style.flex = '1'; rightSideContainer.style.display = 'flex'; rightSideContainer.style.flexDirection = 'column'; container.appendChild(rightSideContainer); const rulesListContainer = document.createElement('div'); rulesListContainer.style.overflowY = 'auto'; rulesListContainer.style.height = 'calc(100% - 81px)'; rightSideContainer.appendChild(rulesListContainer); const addButton = document.createElement('button'); addButton.textContent = 'Add Rule'; addButton.style.margin = '15px auto'; addButton.style.display = 'block'; addButton.style.padding = '10px'; addButton.style.width = '90%'; addButton.style.backgroundColor = 'transparent'; addButton.style.border = CONFIG.BUTTON_OUTLINE; addButton.style.borderRadius = '50px'; addButton.style.cursor = 'pointer'; addButton.addEventListener('mouseenter', () => { addButton.style.backgroundColor = CONFIG.BUTTON_HIGHLIGHT; }); addButton.addEventListener('mouseleave', () => { addButton.style.backgroundColor = 'transparent'; }); addButton.addEventListener('click', () => { const newRule = `<Rule${customRules.length + 1}: Define your rule here>`; customRules.push(newRule); saveCurrentProfileRules(); renderPanel(); }); rightSideContainer.appendChild(addButton); function saveCurrentProfileRules() { profiles[currentProfile] = customRules; saveProfiles(); } function renderPanel() { rulesListContainer.innerHTML = ''; customRules.forEach((rule, index) => { const ruleContainer = document.createElement('div'); ruleContainer.style.marginBottom = '15px'; ruleContainer.style.display = 'flex'; ruleContainer.style.alignItems = 'center'; ruleContainer.style.width = '95%'; ruleContainer.style.gap = '5px'; ruleContainer.style.flexWrap = 'wrap'; const ruleLabel = document.createElement('label'); ruleLabel.textContent = `Rule ${index + 1}:`; ruleLabel.style.color = 'white'; ruleLabel.style.flex = '0.3'; ruleContainer.appendChild(ruleLabel); const ruleInput = document.createElement('textarea'); ruleInput.value = rule.replace(/<Rule\d+: (.*?)>/, '$1'); ruleInput.style.flex = '2'; ruleInput.style.padding = '5px'; ruleInput.style.borderRadius = '5px'; ruleInput.style.border = '0.5px solid #444444'; ruleInput.style.backgroundColor = '#1E1E1E'; ruleInput.style.color = 'gray'; ruleInput.style.overflowY = 'hidden'; ruleInput.style.maxWidth = '100%'; ruleInput.style.boxSizing = 'border-box'; ruleInput.style.resize = 'none'; function adjustHeight(element) { element.style.height = 'auto'; element.style.height = `${element.scrollHeight}px`; } adjustHeight(ruleInput); ruleInput.addEventListener('input', () => { adjustHeight(ruleInput); ruleInput.style.color = '#D16262'; }); ruleContainer.appendChild(ruleInput); const updateButton = document.createElement('button'); updateButton.style.padding = '10px'; updateButton.style.border = 'none'; updateButton.style.color = '#B4B4B4'; updateButton.style.borderRadius = '5px'; updateButton.style.cursor = 'pointer'; // Adding the SVG as the innerHTML of the button updateButton.innerHTML = ` <svg width="14" height="14" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"> <path fill-rule="evenodd" clip-rule="evenodd" d=" M18.1716 1C18.702 1 19.2107 1.21071 19.5858 1.58579L22.4142 4.41421C22.7893 4.78929 23 5.29799 23 5.82843V20C23 21.6569 21.6569 23 20 23H4C2.34315 23 1 21.6569 1 20V4C1 2.34315 2.34315 1 4 1H18.1716ZM4 3C3.44772 3 3 3.44772 3 4V20C3 20.5523 3.44772 21 4 21L5 21L5 15C5 13.3431 6.34315 12 8 12L16 12C17.6569 12 19 13.3431 19 15V21H20C20.5523 21 21 20.5523 21 20V6.82843C21 6.29799 20.7893 5.78929 20.4142 5.41421L18.5858 3.58579C18.2107 3.21071 17.702 3 17.1716 3H17V5C17 6.65685 15.6569 8 14 8H10C8.34315 8 7 6.65685 7 5V3H4ZM17 21V15C17 14.4477 16.5523 14 16 14L8 14C7.44772 14 7 14.4477 7 15L7 21L17 21ZM9 3H15V5C15 5.55228 14.5523 6 14 6H10C9.44772 6 9 5.55228 9 5V3Z " fill="currentColor"/> </svg> `; updateButton.addEventListener('mouseover', () => { updateButton.style.color = '#E3E3E3'; }); updateButton.addEventListener('mouseout', () => { updateButton.style.color = '#B4B4B4'; }); updateButton.addEventListener('click', () => { customRules[index] = `<Rule${index + 1}: ${ruleInput.value}>`; saveCurrentProfileRules(); ruleInput.style.color = 'black'; }); ruleContainer.appendChild(updateButton); const rulesDeleteButton = document.createElement('button'); rulesDeleteButton.style.cssText = 'padding: 5px 10px; margin-right: -20px; color: #B4B4B4; background-color: transparent;'; rulesDeleteButton.innerHTML = ` <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" class="icon-sm"> <path fill-rule="evenodd" clip-rule="evenodd" d=" M10.5555 4C10.099 4 9.70052 4.30906 9.58693 4.75114L9.29382 5.8919H14.715L14.4219 4.75114C14.3083 4.30906 13.9098 4 13.4533 4H10.5555ZM16.7799 5.8919L16.3589 4.25342C16.0182 2.92719 14.8226 2 13.4533 2H10.5555C9.18616 2 7.99062 2.92719 7.64985 4.25342L7.22886 5.8919H4C3.44772 5.8919 3 6.33961 3 6.8919C3 7.44418 3.44772 7.8919 4 7.8919H4.10069L5.31544 19.3172C5.47763 20.8427 6.76455 22 8.29863 22H15.7014C17.2354 22 18.5224 20.8427 18.6846 19.3172L19.8993 7.8919H20C20.5523 7.8919 21 7.44418 21 6.8919C21 6.33961 20.5523 5.8919 20 5.8919H16.7799ZM17.888 7.8919H6.11196L7.30423 19.1057C7.3583 19.6142 7.78727 20 8.29863 20H15.7014C16.2127 20 16.6417 19.6142 16.6958 19.1057L17.888 7.8919ZM10 10C10.5523 10 11 10.4477 11 11V16C11 16.5523 10.5523 17 10 17C9.44772 17 9 16.5523 9 16V11C9 10.4477 9.44772 10 10 10ZM14 10C14.5523 10 15 10.4477 15 11V16C15 16.5523 14.5523 17 14 17C13.4477 17 13 16.5523 13 16V11C13 10.4477 13.4477 10 14 10Z " fill="currentColor"/> </svg> `; rulesDeleteButton.addEventListener('mouseover', () => { rulesDeleteButton.style.color = '#E3E3E3'; }); rulesDeleteButton.addEventListener('mouseout', () => { rulesDeleteButton.style.color = '#B4B4B4'; }); rulesDeleteButton.addEventListener('click', () => { customRules.splice(index, 1); saveCurrentProfileRules(); renderPanel(); }); const moveContainer = document.createElement('div'); moveContainer.style.display = 'flex'; moveContainer.style.flexDirection = 'column'; moveContainer.style.gap = '3px'; if (index > 0) { const upButton = document.createElement('button'); upButton.textContent = '▲'; upButton.style.padding = '3px'; upButton.style.border = 'none'; upButton.style.backgroundColor = 'transparent'; upButton.style.color = '#B4B4B4'; upButton.style.borderRadius = '5px'; upButton.style.cursor = 'pointer'; upButton.addEventListener('click', () => { [customRules[index - 1], customRules[index]] = [customRules[index], customRules[index - 1]]; saveCurrentProfileRules(); renderPanel(); }); moveContainer.appendChild(upButton); } if (index < customRules.length - 1) { const downButton = document.createElement('button'); downButton.textContent = '▼'; downButton.style.padding = '3px'; downButton.style.border = 'none'; downButton.style.backgroundColor = 'transparent'; downButton.style.color = '#B4B4B4'; downButton.style.borderRadius = '5px'; downButton.style.cursor = 'pointer'; downButton.addEventListener('click', () => { [customRules[index], customRules[index + 1]] = [customRules[index + 1], customRules[index]]; saveCurrentProfileRules(); renderPanel(); }); moveContainer.appendChild(downButton); } ruleContainer.appendChild(moveContainer); ruleContainer.appendChild(rulesDeleteButton); rulesListContainer.appendChild(ruleContainer); }); adjustAllHeights(); } function adjustAllHeights() { const textareas = rulesListContainer.querySelectorAll('textarea'); textareas.forEach((textarea) => { textarea.style.height = 'auto'; textarea.style.height = `${textarea.scrollHeight}px`; }); } function updateLayout() { if (isMobile()) { container.style.flexDirection = 'column'; rulesPanel.style.width = '90%'; rulesPanel.style.height = '90%'; rulesListContainer.style.height = 'calc(90% - 60px)'; rulesListContainer.style.overflowY = 'auto'; rulesListContainer.style.maxHeight = `${rulesPanel.clientHeight - 150}px`; // Adjust dynamically profilesContainer.style.display = 'none'; toggleProfilesButton.style.display = 'block'; } else { container.style.flexDirection = 'row'; rulesPanel.style.width = '1000px'; rulesPanel.style.height = '700px'; rulesListContainer.style.height = 'calc(100% - 81px)'; rulesListContainer.style.overflowY = 'auto'; profilesContainer.style.display = 'flex'; toggleProfilesButton.style.display = 'none'; if (profilesOverlay.style.display === 'flex') { profilesOverlay.style.display = 'none'; } if (!container.contains(profilesContainer)) { container.insertBefore(profilesContainer, container.firstChild); } } } window.addEventListener('resize', updateLayout); function openPanel() { rulesPanel.style.display = 'block'; showOverlay(); renderProfilesList(); renderPanel(); updateLayout(); } manageRulesButton.addEventListener('click', () => { if (rulesPanel.style.display === 'none') { openPanel(); } else { closeRulesPanel(); } }); // Initial render renderProfilesList(); updateLayout(); } // ================================================================ INJECT TEXT ================================================================== function injectLogicGPT() { // Variable in which the next rule is stored // const getSelectedRuleValue = localStorage.getItem('selectedRuleValue'); // DETECTING INPUT PANEL function detectInputPanelGPT(callback) { const maxRetries = 10; const retryInterval = 500; let retryCount = 0; const inputPanelGPT = document.querySelector('div#prompt-textarea.ProseMirror'); if (!inputPanelGPT) { console.error('Textarea panel not found.'); if (retryCount < maxRetries) { retryCount++; console.log(`Retrying... Attempt ${retryCount}`); setTimeout(() => detectInputPanelGPT(callback), retryInterval); } else { console.error('Max retries reached. Cannot find the textarea.'); callback(false, null); // Pass null for inputPanelGPT on failure } return; } console.log('Textarea found.'); callback(true, inputPanelGPT); } detectInputPanelGPT(function(success, inputPanelGPT) { if (success) { console.log('Textarea is ready to listen for events.'); } else { console.error('Cannot proceed as textarea was not found.'); } }); // CARRIER FUNCTION TO GET ARRAYS OF ALL THOSE MESSAGES function getLastMessages(type) { console.log(`${type === 'user' ? 'getLastUserMessage' : 'getLastGPTMessage'} function called`); return new Promise((resolve, reject) => { let retryCount = 0; const maxRetries = 5; const retryInterval = 1000; // 1 second const selector = type === 'user' ? '.whitespace-pre-wrap' : 'div.markdown.prose.w-full.break-words.dark\\:prose-invert'; const storageKey = type === 'user' ? 'lastUserMessage' : 'lastGPTMessage'; const storageKeyTen = type === 'user' ? 'lastTenMessages' : 'lastTenGPTMessages'; function attemptRetrieval() { const messageElementArray = Array.from(document.querySelectorAll(selector)); if (messageElementArray.length > 0) { const lastMessage = messageElementArray.slice(-1)[0].textContent.trim(); console.log(`Last ${type === 'user' ? 'User' : 'GPT'} Message:`, lastMessage); localStorage.setItem(storageKey, lastMessage); const lastTenMessages = messageElementArray.slice(-10).map(element => element.textContent.trim()); console.log(`Last 10 ${type === 'user' ? 'User' : 'GPT'} Messages:`, lastTenMessages); localStorage.setItem(storageKeyTen, JSON.stringify(lastTenMessages)); resolve(lastMessage); // Resolve the promise with the last message return; // Stop further retries } if (retryCount < maxRetries) { retryCount++; console.log(`Retrying... Attempt ${retryCount}`); setTimeout(attemptRetrieval, retryInterval); } else { console.error(`Max retries reached. No ${type === 'user' ? 'user' : 'GPT'} message found.`); localStorage.setItem(storageKey, ''); reject(new Error(`Failed to retrieve ${type} message.`)); } } function monitorNetworkForPOST() { const observer = new PerformanceObserver((list) => { const entries = list.getEntries(); for (const entry of entries) { if ( entry.initiatorType === 'fetch' && (entry.name.includes('https://chatgpt.com/backend-api/conversation') || entry.name.includes('https://chatgpt.com/ces/v1/p')) ) { console.log("Detected POST to https://chatgpt.com/backend-api/conversation. Resetting retry count..."); retryCount = 0; // Reset retry count on new POST detection attemptRetrieval(); // Retry retrieval immediately } } }); observer.observe({ type: 'resource', buffered: true }); } monitorNetworkForPOST(); attemptRetrieval(); }); } // Example usage of getLastMessages getLastMessages('user', function(success, lastUserMessage) { if (success) { console.log("Retrieved last user message:", lastUserMessage); } else { console.error("Failed to retrieve last user message."); //When there's no User Message reset the Rules Counter const getRulesState = localStorage.getItem('enableRules'); if (getRulesState === "true") { const selectedProfileRules = localStorage.getItem('selectedProfile.Rules'); const rulesProfiles = JSON.parse(localStorage.getItem('rulesProfiles')); const selectedRules = rulesProfiles[selectedProfileRules]; console.log(`Stored selectedRules: ${selectedRules}`); const initNextRule = 'Rule1'; localStorage.setItem('nextRule', initNextRule); const initPreviousRule = localStorage.setItem('previousRule', '0'); const initNextRuleValue = selectedRules.find(rule => rule.startsWith(`<${initNextRule}:`)); localStorage.setItem('selectedRuleValue', initNextRuleValue); console.log(`Initial stored selectedRuleValue: ${initNextRuleValue}`); } } }); getLastMessages('gpt', function(success, lastGPTMessage) { if (success) { console.log("Retrieved last GPT message:", lastGPTMessage); } else { console.error("Failed to retrieve last GPT message."); } }); // ================================================================= RULES LOGIC ================================================================== function rulesLogic() { // CHECKING IF THE MODULES ARE ENABLED const selectedProfileRules = localStorage.getItem('selectedProfile.Rules'); const rulesProfiles = JSON.parse(localStorage.getItem('rulesProfiles')); const selectedRules = rulesProfiles[selectedProfileRules]; console.log(`Stored selectedRules: ${selectedRules}`); const initNextRule = 'Rule1'; localStorage.setItem('nextRule', initNextRule); const initPreviousRule = localStorage.setItem('previousRule', '0'); const initNextRuleValue = selectedRules.find(rule => rule.startsWith(`<${initNextRule}:`)); localStorage.setItem('selectedRuleValue', initNextRuleValue); console.log(`Initial stored selectedRuleValue: ${initNextRuleValue}`); const getRulesState = localStorage.getItem('enableRules'); if (getRulesState === "true") { // RETRIEVING THE LAST USER MESSAGE const lastUserMessage = localStorage.getItem('lastUserMessage'); if (lastUserMessage) { // MATCHING RULES IN THE MESSAGE const ruleMatches = lastUserMessage.match(/<Rule\d+/g); if (ruleMatches) { console.log('Found rules:', ruleMatches); // STORING THE LAST MATCHED RULE AS "previousRule" const previousRule = ruleMatches[ruleMatches.length - 1].replace('<', ''); localStorage.setItem('previousRule', previousRule); // CALCULATING AND STORING THE NEXT RULE const ruleNumber = parseInt(previousRule.replace('Rule', ''), 10); const nextRuleNumber = (ruleNumber % selectedRules.length) + 1; // Wrap around using modulus const nextRule = `Rule${nextRuleNumber}`; localStorage.setItem('nextRule', nextRule); console.log(`Stored previousRule: ${previousRule}`); console.log(`Stored nextRule: ${nextRule}`); const nextRuleValue = selectedRules.find(rule => rule.startsWith(`<${nextRule}:`)); localStorage.setItem('selectedRuleValue', nextRuleValue); console.log(`Stored selectedRuleValue: ${nextRuleValue}`); } else { console.log('No rules found in the last user message.'); } } else { console.log('No last user message found in localStorage.'); } } else { console.log('Rules module is disabled.'); } } function observeLocalStorageKeyChange(key, callback) { let previousValue = localStorage.getItem(key); setInterval(() => { const currentValue = localStorage.getItem(key); if (currentValue !== previousValue) { previousValue = currentValue; callback(currentValue); } }, 100); // Adjust the interval as needed } // Set up the observer for 'lastUserMessage' observeLocalStorageKeyChange('lastUserMessage', (newValue) => { console.log(`Detected change in 'lastUserMessage': ${newValue}`); rulesLogic(); }); rulesLogic(); } // ================================================================ TEXT COLORS ================================================================== function colorsScript() { const defaultColors = { textColor: '#A2A2AC', emColor: '#E0DF7F', bracketHighlight: '#737373', whiteHighlight: '#FFFFFF' }; // Load colors from localStorage or use default colors function loadColors() { return { textColor: localStorage.getItem('textColor') || defaultColors.textColor, emColor: localStorage.getItem('emColor') || defaultColors.emColor, bracketHighlight: localStorage.getItem('bracketHighlight') || defaultColors.bracketHighlight, whiteHighlight: localStorage.getItem('whiteHighlight') || defaultColors.whiteHighlight }; } // Inject styles based on the loaded colors function injectStyles(colors) { const styleId = 'colorizer-styles'; let styleElement = document.getElementById(styleId); if (!styleElement) { styleElement = document.createElement('style'); styleElement.id = styleId; document.head.appendChild(styleElement); } styleElement.textContent = ` p, div.whitespace-pre-wrap { color: ${colors.textColor}; } em { color: ${colors.emColor} !important; font-weight: normal !important; } .highlight-blue { color: ${colors.bracketHighlight} !important; } .highlight-white { color: ${colors.whiteHighlight} !important; } .highlight-blue * { color: inherit !important; } .highlight-white * { color: inherit !important; } `; } // Create the color picker panel UI function createColorPickerPanel() { const colors = loadColors(); const colorPanel = document.createElement('div'); colorPanel.id = 'color-picker-panel'; colorPanel.style.position = 'fixed'; // Center the panel colorPanel.style.top = '50%'; colorPanel.style.left = '50%'; colorPanel.style.transform = 'translate(-50%, -50%)'; // Precise centering colorPanel.style.padding = '30px'; // Increased padding colorPanel.style.background = '#2F2F2F'; // Darker, cooler background colorPanel.style.color = '#f8f8f8'; // Light, readable text color colorPanel.style.borderRadius = '20px'; // More rounded corners colorPanel.style.zIndex = '10000'; colorPanel.style.display = 'none'; // colorPanel.style.fontFamily = 'sans-serif'; // Modern font // colorPanel.style.border = '1px solid #44475a'; // Subtle border colorPanel.innerHTML = ` <h3 style="margin-top:0; margin-bottom: 20px; text-align: center; color: #f8f8f8;">Customize Text Colors</h3> <div style="margin-bottom: 15px;"> <label style="display: inline-block; width: 120px; margin-right: 10px;">Text Color:</label> <input type="color" id="textColor" value="${colors.textColor}" style="width: 50px; height: 30px; vertical-align: middle; border: none; cursor: pointer;"> </div> <div style="margin-bottom: 15px;"> <label style="display: inline-block; width: 120px; margin-right: 10px;">Italic:</label> <input type="color" id="emColor" value="${colors.emColor}" style="width: 50px; height: 30px; vertical-align: middle; border: none; cursor: pointer;"> </div> <div style="margin-bottom: 15px;"> <label style="display: inline-block; width: 120px; margin-right: 10px;">Parentheses:</label> <input type="color" id="bracketHighlight" value="${colors.bracketHighlight}" style="width: 50px; height: 30px; vertical-align: middle; border: none; cursor: pointer;"> </div> <div> <label style="display: inline-block; width: 120px; margin-right: 10px;">Quotes:</label> <input type="color" id="whiteHighlight" value="${colors.whiteHighlight}" style="width: 50px; height: 30px; vertical-align: middle; border: none; cursor: pointer;"> </div> <div style="text-align: right; margin-top: 25px;"> <button id="saveColors" style="padding: 8px 15px; background-color: transparent; color: #f8f8f8; border: 1px solid #4E4E4E; border-radius: 50px; cursor: pointer; margin-right: 10px;">Save</button> <button id="closePanel" style="padding: 8px 15px; background-color: transparent; color: #f8f8f8; border: 1px solid #4E4E4E; border-radius: 50px; cursor: pointer;">Close</button> </div> `; document.body.appendChild(colorPanel); document.getElementById('saveColors').addEventListener('click', () => { saveColors(); colorPanel.style.display = 'none'; }); document.getElementById('closePanel').addEventListener('click', () => { colorPanel.style.display = 'none'; }); } // Create the manage colors button window.colorButton = document.createElement('div'); window.colorButton.innerHTML = ` <button id="toggle-color-panel" style=" position: relative; top: 10px; right: 0px; left: 10px; padding: 7px 15px; background: transparent; color: #b0b0b0; border: none; border-radius: 8px; font-size: 16px; text-align: left; cursor: pointer; width: 90%; display: flex; align-items: center; gap: 10px; transition: background-color 0.1s, color 0.1s; z-index: 1001;"> <svg fill="#B0B0B0" viewBox="0 0 32 32" width="16px" height="16px" xmlns="http://www.w3.org/2000/svg"> <g id="SVGRepo_bgCarrier" stroke-width="0"></g> <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g> <g id="SVGRepo_iconCarrier"> <title>brush</title> <path d="M27.555 8.42c-1.355 1.647-5.070 6.195-8.021 9.81l-3.747-3.804c3.389-3.016 7.584-6.744 9.1-8.079 2.697-2.377 5.062-3.791 5.576-3.213 0.322 0.32-0.533 2.396-2.908 5.286zM18.879 19.030c-1.143 1.399-2.127 2.604-2.729 3.343l-4.436-4.323c0.719-0.64 1.916-1.705 3.304-2.939l3.861 3.919zM15.489 23.183v-0.012c-2.575 9.88-14.018 4.2-14.018 4.2s4.801 0.605 4.801-3.873c0-4.341 4.412-4.733 4.683-4.753l4.543 4.427c0 0.001-0.009 0.011-0.009 0.011z"></path> </g> </svg> Manage Colors </button> `; const colorButtonElement = window.colorButton.querySelector('button'); colorButtonElement.onmouseover = () => { colorButtonElement.style.backgroundColor = '#212121'; colorButtonElement.style.color = '#ffffff'; }; colorButtonElement.onmouseout = () => { colorButtonElement.style.backgroundColor = 'transparent'; colorButtonElement.style.color = '#b0b0b0'; }; // Toggle the color picker panel visibility window.colorButton.addEventListener('click', () => { const colorPanel = document.getElementById('color-picker-panel'); if (colorPanel) { colorPanel.style.display = colorPanel.style.display === 'none' ? 'block' : 'none'; } }); // Save the selected colors to localStorage and update styles function saveColors() { const textColor = document.getElementById('textColor').value; const emColor = document.getElementById('emColor').value; const bracketHighlight = document.getElementById('bracketHighlight').value; const whiteHighlight = document.getElementById('whiteHighlight').value; localStorage.setItem('textColor', textColor); localStorage.setItem('emColor', emColor); localStorage.setItem('bracketHighlight', bracketHighlight); localStorage.setItem('whiteHighlight', whiteHighlight); injectStyles(loadColors()); // Re-highlight existing messages to apply new colors processExistingMessages(); // Optional: Provide a non-intrusive notification instead of alert showTemporaryNotification('Colors saved successfully!', 2000); } // Function to show a temporary notification function showTemporaryNotification(message, duration) { const notification = document.createElement('div'); notification.textContent = message; notification.style.position = 'fixed'; notification.style.bottom = '20px'; notification.style.right = '20px'; notification.style.padding = '10px 20px'; notification.style.backgroundColor = 'rgba(0, 0, 0, 0.8)'; notification.style.color = '#fff'; notification.style.borderRadius = '5px'; notification.style.zIndex = '10001'; notification.style.opacity = '0'; notification.style.transition = 'opacity 0.5s'; document.body.appendChild(notification); // Trigger reflow to apply transition void notification.offsetWidth; notification.style.opacity = '1'; setTimeout(() => { notification.style.opacity = '0'; setTimeout(() => { document.body.removeChild(notification); }, 500); }, duration); } // Retaining the original functions for message highlighting let debounceTimer = null; // Function to highlight message content function highlightMessageContent(messageElement) { if (!messageElement || messageElement.dataset.processed) return; console.log('highlightMessageContent'); // Exclude elements inside the #prompt-textarea if (messageElement.closest('#prompt-textarea')) return; // Process for parentheses and quotes safelyColorText(messageElement, /\(([^)]+)\)/g, 'highlight-blue'); // Parentheses safelyColorText(messageElement, /["“](.*?)["”]/g, 'highlight-white'); // Quotes // Mark as processed to avoid reprocessing static messages messageElement.dataset.processed = 'true'; } // Function to safely color text based on regex function safelyColorText(container, regex, highlightClass) { const walker = document.createTreeWalker(container, NodeFilter.SHOW_TEXT, null, false); const nodesToProcess = []; let node; while ((node = walker.nextNode())) { // Skip processing for nodes inside the #prompt-textarea or editable areas if ( node.parentElement.closest('#prompt-textarea') || node.parentElement.closest('.prosemirror-editor-container') || node.parentElement.closest('[contenteditable="true"]') ) continue; nodesToProcess.push(node); } nodesToProcess.forEach(node => { const parent = node.parentNode; const text = node.textContent; let newHTML = ''; let lastIndex = 0; regex.lastIndex = 0; // Reset regex state let match; while ((match = regex.exec(text)) !== null) { newHTML += escapeHTML(text.substring(lastIndex, match.index)); newHTML += `<span class="${highlightClass}">${escapeHTML(match[0])}</span>`; lastIndex = regex.lastIndex; } newHTML += escapeHTML(text.substring(lastIndex)); if (newHTML !== escapeHTML(text)) { const tempSpan = document.createElement('span'); tempSpan.innerHTML = newHTML; parent.replaceChild(tempSpan, node); } }); } // Function to escape HTML entities function escapeHTML(str) { return str.replace(/&/g, "&") .replace(/</g, "<") .replace(/>/g, ">") .replace(/"/g, """) .replace(/'/g, "'"); } // Function to process existing messages function processExistingMessages() { const messages = document.querySelectorAll('p, div.whitespace-pre-wrap'); messages.forEach(message => { console.log('processExistingMessages'); highlightMessageContent(message); }); } // NEW FUNCTION TO MONITOR THE STREAMING ELEMENT /*function observeStreamingMessages() { const streamingMessage = document.querySelector('.result-streaming.markdown.prose.w-full.break-words.dark\\:prose-invert.dark'); if (!streamingMessage) return; const streamingObserver = new MutationObserver(mutations => { // Any time the streaming element updates, re-highlight its content. highlightMessageContent(streamingMessage); // Remove the 'processed' attribute so we can continuously reprocess as new text comes in. streamingMessage.removeAttribute('data-processed'); }); streamingObserver.observe(streamingMessage, { childList: true, subtree: true, characterData: true }); } */ // NEW FUNCTION TO MONITOR Network POST Requests with 2-Second Cooldown function monitorNetworkForPOST() { let isCooldown = false; // Flag to manage cooldown const observer = new PerformanceObserver((list) => { const entries = list.getEntries(); for (const entry of entries) { if ( entry.initiatorType === 'fetch' && ( entry.name.includes('https://chatgpt.com/backend-api/conversation') || entry.name.includes('https://chatgpt.com/ces/v1/p') || entry.name.includes('https://ab.chatgpt.com/v1/rgstr') ) ) { if (isCooldown) { console.log("POST event detected but cooldown active. Ignoring."); continue; } console.log("Detected POST to backend API. Processing messages..."); isCooldown = true; // Activate cooldown attemptRetrieval(); // Retry retrieval immediately processExistingMessages(); // Process messages after POST detection // Set a timeout to reset the cooldown after 2 seconds setTimeout(() => { isCooldown = false; console.log("Cooldown period ended. Ready to process next POST event."); }, 1000); // 2000 milliseconds = 2 seconds } } }); observer.observe({ type: 'resource', buffered: true }); } // Function to initialize the highlighting functionality function initialize() { console.log('initialize'); const colors = loadColors(); injectStyles(colors); // Inject styles only once during initialization createColorPickerPanel(); processExistingMessages(); // observeStreamingMessages(); // Observe streaming content with debouncing monitorNetworkForPOST(); // Monitor network POST events } // Function to attempt retrieval (assuming it's defined elsewhere) function attemptRetrieval() { // Implementation of attemptRetrieval console.log('attemptRetrieval called'); // Add your retrieval logic here } // Function to start initialization if colors are enabled function startInitialization() { const getColorsState = localStorage.getItem('enableColors'); if (getColorsState === "true") { initialize(); } else { console.log("Color customization is disabled."); } } // Ensure the script initializes correctly on page load if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', startInitialization); } else { startInitialization(); } } // =================================================================== < > Hider =================================================================== function hideInjectionsScript() { // Mutation observer reference let observer = null; // Function to hide text within angle brackets function hideBracketText(node) { const regex = /<([^>]+)>/g; // Ensure the node is a text node if (node.nodeType === Node.TEXT_NODE) { const parent = node.parentNode; // Exclude nodes inside certain elements if (!parent.closest('div.whitespace-pre-wrap')) { return; } const matches = [...node.nodeValue.matchAll(regex)]; if (matches.length > 0) { let lastIndex = 0; matches.forEach(match => { const before = document.createTextNode(node.nodeValue.slice(lastIndex, match.index)); const hiddenSpan = document.createElement('span'); hiddenSpan.style.display = 'none'; // Hide the text hiddenSpan.textContent = match[0]; // Include the full match (e.g., <text>) parent.insertBefore(before, node); parent.insertBefore(hiddenSpan, node); lastIndex = match.index + match[0].length; }); const after = document.createTextNode(node.nodeValue.slice(lastIndex)); parent.insertBefore(after, node); parent.removeChild(node); } } } // Process only visible and editable elements function processVisibleTextNodes() { document.querySelectorAll('*:not(script):not(style)').forEach(node => { if (node.childNodes && node.offsetParent !== null) { // Ensures visibility node.childNodes.forEach(child => { if (child.parentNode.closest('div.whitespace-pre-wrap')) { hideBracketText(child); } }); } }); } // Start observing the DOM function startObserving() { if (observer) return; // Avoid multiple observers observer = new MutationObserver(mutations => { mutations.forEach(mutation => { mutation.addedNodes.forEach(addedNode => { if (addedNode.nodeType === Node.ELEMENT_NODE) { if (addedNode.closest('div.whitespace-pre-wrap')) { processVisibleTextNodes(); } } else if (addedNode.nodeType === Node.TEXT_NODE) { if (addedNode.parentNode.closest('div.whitespace-pre-wrap')) { hideBracketText(addedNode); } } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); processVisibleTextNodes(); // Process existing nodes initially } // Stop observing the DOM function stopObserving() { if (observer) { observer.disconnect(); observer = null; } } // Show hidden text function showBracketText() { document.querySelectorAll('span[style*="display: none"]').forEach(hiddenSpan => { const parent = hiddenSpan.parentNode; const textNode = document.createTextNode(hiddenSpan.textContent); parent.insertBefore(textNode, hiddenSpan); parent.removeChild(hiddenSpan); }); } // Monitor toggle state function monitorHiderState() { const state = localStorage.getItem('enableHider'); if (state === 'true') { console.log("Hider is enabled."); showBracketText(); // Reset to avoid duplicates startObserving(); } else { console.log("Hider is disabled."); stopObserving(); showBracketText(); // Reveal hidden text } } // Monitor network for specific POST requests function monitorNetworkForPOST() { const performanceObserver = new PerformanceObserver((list) => { const entries = list.getEntries(); for (const entry of entries) { if ( entry.initiatorType === 'fetch' && (entry.name.includes('https://chatgpt.com/backend-api/conversation') || entry.name.includes('https://chatgpt.com/ces/v1/p')) ) { console.log("Detected POST request. Activating hiding script."); monitorHiderState(); // Adjust state based on toggle } } }); performanceObserver.observe({ type: 'resource', buffered: true }); } // Listen for storage changes window.addEventListener('storage', monitorHiderState); // Initial setup monitorHiderState(); monitorNetworkForPOST(); } // ============================================================= CONTENT WARNINGS ================================================================= function hideContentWarnings() { function updateVisibility() { const state = localStorage.getItem('enableHideWarning'); if (state === 'true') { GM_addStyle(` .border-orange-400\\/15, div.text-sm.text-orange-600.border-token-border-light.bg-orange-400.bg-opacity-0.w-full.pr-5.text-right { display: none !important; } `); } else { GM_addStyle(` .border-orange-400\\/15, div.text-sm.text-orange-600.border-token-border-light.bg-orange-400.bg-opacity-0.w-full.pr-5.text-right { display: block !important; } `); } } // Initial update updateVisibility(); // Watch for changes in localStorage window.addEventListener('storage', (event) => { if (event.key === 'enableHideWarning') { updateVisibility(); } }); // Optional: Add a periodic check as a fallback setInterval(updateVisibility, 1000); } // Call the function to initialize hideContentWarnings(); // =================================================================== BUTTONS =================================================================== function createDivider() { const divider = document.createElement('div'); divider.style.height = '1px'; divider.style.backgroundColor = '#212121'; divider.style.margin = '20px 20px 0px 20px'; return divider; } function createFooterText() { const footerText = document.createElement('div'); footerText.textContent = '© Vishanka 2024'; footerText.style.position = 'absolute'; footerText.style.bottom = '10px'; footerText.style.left = '50%'; footerText.style.transform = 'translateX(-50%)'; footerText.style.fontSize = '12px'; footerText.style.fontWeight = '550'; footerText.style.color = '#272727'; return footerText; } function createCheckbox(label, key) { const checkboxContainer = document.createElement('div'); checkboxContainer.style.marginTop = '5px'; checkboxContainer.style.marginLeft = '25px'; const checkboxLabel = document.createElement('label'); checkboxLabel.style.color = '#B0B0B0'; const checkbox = document.createElement('input'); checkbox.style.marginRight = '10px'; checkbox.type = 'checkbox'; checkbox.id = key; checkboxLabel.textContent = label; checkboxLabel.setAttribute('for', key); // Retrieve saved state from localStorage const savedState = localStorage.getItem(key); if (savedState !== null) { checkbox.checked = savedState === 'true'; } // Listen for changes and save state to localStorage checkbox.addEventListener('change', function() { localStorage.setItem(key, checkbox.checked); }); checkboxContainer.appendChild(checkbox); checkboxContainer.appendChild(checkboxLabel); return checkboxContainer; } function initializeCheckboxes() { function checkboxDivider() { const checkboxDivider = document.createElement('div'); checkboxDivider.style.height = '1px'; checkboxDivider.style.backgroundColor = '#212121'; checkboxDivider.style.margin = '20px 20px 20px 20px'; return checkboxDivider; } // Create a container for the checkboxes const checkboxGroup = document.createElement('div'); checkboxGroup.style.marginTop = '15px'; // Add margin at the top of the group // Create and append each checkbox to the group checkboxGroup.appendChild(createCheckbox('Enable Rules', 'enableRules')); checkboxGroup.appendChild(createCheckbox('Enable Lorebook', 'enableLorebook')); checkboxGroup.appendChild(createCheckbox('Enable Events', 'enableEvents')); checkboxGroup.appendChild(checkboxDivider()); checkboxGroup.appendChild(createCheckbox('Enable Colors', 'enableColors')); checkboxGroup.appendChild(createCheckbox('Hide Injections', 'enableHider')); checkboxGroup.appendChild(createCheckbox('Hide Content Warning', 'enableHideWarning')); // Append the group to the main panel mainPanel.appendChild(checkboxGroup); } function initializeButton() { mainPanel.appendChild(createDivider()); mainPanel.appendChild(manageRulesButton); mainPanel.appendChild(createDivider()); initializeCheckboxes(); mainPanel.appendChild(createDivider()); mainPanel.appendChild(colorButton); mainPanel.appendChild(createFooterText()); } // ============================================================ SCRIPT LOADING ORDER ============================================================ colorsScript(); hideInjectionsScript(); hideContentWarnings(); mainPanelScript(); rulesScript(); initializeButton(); injectLogicGPT(); // Function to execute your scripts /* function executeScripts() { mainPanelScript(); rulesScript(); initializeButton(); injectLogicGPT(); } // Initial execution executeScripts(); // Monitor for URL changes let currentUrl = location.href; const observer = new MutationObserver(() => { if (currentUrl !== location.href) { currentUrl = location.href; console.log('URL changed, re-executing scripts...'); executeScripts(); } }); // Observe changes in the <body> tag observer.observe(document.body, { childList: true, subtree: true }); */ })();