/* * ThunderAI [https://micz.it/thunderbird-addon-thunderai/] * Copyright (C) 2024 Mic (m@micz.it) * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ // Some original methods derived from https://github.com/KudoAI/chatgpt.js/blob/7eb8463cd61143fa9e1d5a8ec3c14d3c1b286e54/chatgpt.js // Using a full string to inject it in the ChatGPT page to avoid any security error export const mzta_script = ` let force_go = false; let current_message = null; async function chatgpt_sendMsg(msg, method ='') { // return -1 send button not found, -2 textarea not found const textArea = document.querySelector('form textarea'), sendButton = document.querySelector('path[d*="M15.192 8.906a1.143"]')?.parentNode.parentNode // post-GPT-4o; || document.querySelector('[data-testid="send-button"]'); // pre-GPT-4o //check if the textarea has been found if(!textArea) { return -2; } textArea.value = msg; textArea.dispatchEvent(new Event('input', { bubbles: true })); // enable send button //check if the sendbutton has been found if (!sendButton) { return -1; } const delaySend = setInterval(() => { if (!sendButton?.hasAttribute('disabled')) { // send msg method.toLowerCase() == 'click' ? sendButton.click() : textArea.dispatchEvent(new KeyboardEvent('keydown', { keyCode: 13, bubbles: true })); clearInterval(delaySend); } }, 25); return 0; //everything is ok } async function chatgpt_isIdle() { return new Promise(resolve => { const intervalId = setInterval(() => { if (chatgpt_getRegenerateButton()) { clearInterval(intervalId); resolve(true); }}, 100);});} function chatgpt_getRegenerateButton() { for (const mainSVG of document.querySelectorAll('main svg')) { if (mainSVG.querySelector('path[d*="M3.07 10.876C3.623"]')) // regen icon found return mainSVG.parentNode.parentNode; } } async function chatgpt_getFromDOM(pos) { const responseDivs = document.querySelectorAll('div[data-testid*="conversation-turn"]:nth-child(odd)'), strPos = pos.toString().toLowerCase(); //console.log(">>>>>>>>>>>>> responseDivs.length: "+ responseDivs.length); let response = ''; if (responseDivs.length) { if (/last|final/.test(strPos)){ // get last response responseDivs[responseDivs.length - 1].innerHTML = responseDivs[responseDivs.length - 1].innerHTML.replace(/<\\/p>/g, '

\\n\\n').replace(//g, '
\\n'); // Removing the new buttons that let the user change model and insert a number (4 or 3.5 at the end of the text) let parser = new DOMParser(); let doc = parser.parseFromString(responseDivs[responseDivs.length - 1].innerHTML, 'text/html'); if(!mztaKeepFormatting) { // Return only TEXT // Select the div with class 'empty:hidden' let correct_div = responseDivs[responseDivs.length - 1].querySelector('div[data-message-author-role="assistant"]'); response = correct_div.textContent; //console.log(">>>>>>>>>> response: " + response); response = response.replace(/^ChatGPT(?:ChatGPT)?/, ''); // strip sender name response = response.trim().replace(/^"|"$/g, ''); // strip quotation marks response = "

" + response + "

"; //console.log(">>>>>>>>> response: " + JSON.stringify(response)); let parser_2 = new DOMParser(); let doc_response = parser_2.parseFromString(response, 'text/html'); //console.log(">>>>>>>>> doc_response: " + JSON.stringify(doc_response.body.innerHTML)); replaceNewlinesWithBr(doc_response.body) response = doc_response.body.innerHTML; } else { // Return HTML // Tags to exclude //console.log(">>>>>>>>> doc.body.innerHTML original: " + doc.body.innerHTML); const excludeTags = ['div', 'text', 'svg', 'path', 'button']; const includeTags = ['p', 'ul']; // removeTags(doc.body, excludeTags); response = removeTagsAndReturnHTML(doc.body, excludeTags, includeTags) //console.log(">>>>>>>>> doc.body.innerHTML final: " + doc.body.innerHTML); // response = doc.body.innerHTML; } //console.log('chatgpt_getFromDOM final response: '+response); //console.log('chatgpt_getFromDOM: [HTML] ' + responseDivs[responseDivs.length - 1].innerHTML.replace(/]*>/gi, '').replace(/<\\/div>/gi, '').replace(/]*>/gi, '').replace(/<\\/svg>/gi, '').replace(/]*>/gi, '').replace(/<\\/path>/gi, '').replace(/]*>/gi, '').replace(/<\\/text>/gi, '').replace(/]*>/gi, '').replace(/<\\/span>/gi, '').replace(/]*>/gi, '').replace(/<\\/button>/gi, '')); } else { // get nth response --- HERE ONLY TEXT FROM RESPONSE, NO HTML const nthOfResponse = ( // Calculate base number Number.isInteger(pos) ? pos : // do nothing for integers /^\d+/.test(strPos) ? /^\d+/.exec(strPos)[0] : // extract first digits for strings w/ them ( // convert words to integers for digitless strings /^(?:1|one|fir)(?:st)?$/.test(strPos) ? 1 : /^(?:2|tw(?:o|en|el(?:ve|f))|seco)(?:nd|t[yi])?(?:e?th)?$/.test(strPos) ? 2 : /^(?:3|th(?:ree|ir?))(?:rd|teen|t[yi])?(?:e?th)?$/.test(strPos) ? 3 : /^(?:4|fou?r)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 4 : /^(?:5|fi(?:ve|f))(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 5 : /^(?:6|six)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 6 : /^(?:7|seven)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 7 : /^(?:8|eight?)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 8 : /^(?:9|nine?)(?:teen|t[yi])?(?:e?th)?$/.test(strPos) ? 9 : /^(?:10|ten)(?:th)?$/.test(strPos) ? 10 : 1 ) // Transform base number if suffixed * ( /(ty|ieth)$/.test(strPos) ? 10 : 1 ) // x 10 if -ty/ieth + ( /teen(th)?$/.test(strPos) ? 10 : 0 ) // + 10 if -teen/teenth ); response = responseDivs[nthOfResponse - 1].textContent; } //console.log('>>>>>>>>>>>>>> chatgpt_getFromDOM: ' + JSON.stringify(response)); } return response; } function chatpgt_scrollToBottom () { try { document.querySelector('button[class*="cursor"][class*="bottom"]').click(); } catch (err) { console.error('[ThunderAI] ', err); } } function addCustomDiv(prompt_action,tabId,mailMessageId) { // Create