// ==UserScript== // @name Change ChatGPT Image And Text To Speech Function // @namespace Change ChatGPT Image And Text To Speach Function // @version 0.2 // @description ChatGPT // @author kaes-u-paya for text to speech and mei for the image change // @match https://chat.openai.com/chat // @grant none // @license MIT // @downloadURL https://update.greasyfork.icu/scripts/458451/Change%20ChatGPT%20Image%20And%20Text%20To%20Speech%20Function.user.js // @updateURL https://update.greasyfork.icu/scripts/458451/Change%20ChatGPT%20Image%20And%20Text%20To%20Speech%20Function.meta.js // ==/UserScript== //var link = "https://s3.bmp.ovh/imgs/2022/12/18/f2294e4eb27e9161.jpg"; var link = "https://cdn4.iconfinder.com/data/icons/artificial-intelligence-35/64/artificial-intelligence-ai-avatar-robot-512.png"; var circle = false; var shadow = false; var VoiceSettingsTags = `
1 1 1
`; document.head.appendChild(Object.assign(document.createElement("style"), {textContent: ` .properties { position:absolute; z-index:10000; width: 430px; top:5px; right:5px; display: grid; grid-template-columns: max-content minmax(0, auto) 40px; gap: 10px; padding: 10px; background-color: #0003; } #voice { padding-top:0px; height: 30px; font-size: 14px; background: rgba(0, 0, 0, 0.5); color: #fff; text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4); } ` })); let VoiceSettings = document.createElement('div'); VoiceSettings.innerHTML = VoiceSettingsTags; document.body.appendChild(VoiceSettings); //var textinput = "Hi how are you?"; document.addEventListener("DOMNodeInserted", function(event) { /* * alert('inserted ' + event.target.childNodes[0].childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('img')[1].alt);// new node -- extract your name from google account avatar logo alt text */ /* try { let AiLogo = event.target.childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('svg')[0].getAttribute("class"); // find the event when the AI logo will be inserted - class -> 'h-6 w-6' } catch (event) { if (event.name === 'TypeError') { //element doesnt exist yet (undefined) - wait for the element to be created } else { throw event; // re-throw the error } } */ let AiLogo = event.target.childNodes[0].childNodes[0].childNodes[0].getElementsByTagName('svg')[0].getAttribute("class"); // find the event when the AI logo will be inserted - class -> 'h-6 w-6' if (AiLogo === 'h-6 w-6'){ //now swap the logo with the custom logo let elementsSVG = document.querySelectorAll('.flex.flex-col.relative.items-end svg'); elementsSVG.forEach(function(elementSVG) { var imgElement = document.createElement("img"); imgElement.src = link; if(circle){imgElement.style.borderRadius = "14px";} if(shadow){imgElement.style.boxShadow = "0 2px 4px rgba(0,0,0,6)";} elementSVG.parentNode.replaceChild(imgElement, elementSVG); }); let elementsRound = document.querySelectorAll('.relative.p-1.rounded-sm.text-white.flex.items-center.justify-center'); elementsRound.forEach(function(elementRound) { elementRound.style.padding = '0'; if(circle){elementRound.style.borderRadius = "14px";} }); } /* try { let AiAnswer = event.target.childNodes[0].childNodes[1].childNodes[0].getElementsByTagName('div')[0].getAttribute("class"); //find the event when the AI gives an answer } catch (event) { if (event.name === 'TypeError') { //element doesnt exist yet (undefined) - wait for the element to be created } else { throw event; // re-throw the error } } */ let AiAnswer = event.target.childNodes[0].childNodes[1].childNodes[0].getElementsByTagName('div')[0].getAttribute("class"); //find the event when the AI gives an answer if (AiAnswer === 'min-h-[20px] flex flex-col items-start gap-4 whitespace-pre-wrap'){ //alert (event.relatedNode.innerHTML); let collectionA = document.getElementsByClassName('w-full border-b border-black/10 dark:border-gray-900/50 text-gray-800 dark:text-gray-100 group bg-gray-50 dark:bg-[#444654]'); //maybe that tag is different if you don't unse the dark theme! var cLL = collectionA.length; if (cLL > 0){ var readcounter = 0; var countnochange = 0; var delay = 6000; //Delay for one loop = 6 seconds var cutstart = 0; var cutend = 0; var cut1 = 0; var cut2 = 0; var speakstring = ''; var oldlenght = 0; var myLoop = setInterval(function() { var currentLL = collectionA[cLL-1].childNodes[0].childNodes[1].childNodes[0].childNodes[0].childNodes[0].innerHTML; currentLL = currentLL.substr(3,currentLL.length-2); if (currentLL.length > oldlenght){ oldlenght = currentLL.length; countnochange = 0; } readcounter++; var posd = currentLL.lastIndexOf('.')+1; var posp = currentLL.lastIndexOf(':')+1; var pose = currentLL.lastIndexOf('!')+1; var posq = currentLL.lastIndexOf('?')+1; var posb = currentLL.lastIndexOf(',')+1; var posX = currentLL.lastIndexOf(' ')+1; console.log ('posd: '+posd+' posp: '+posp+' pose: '+pose+' posq: '+posq+' posb: '+posb+' posX: '+posX); if (posd > cut1) {cut1 = posd;} if (posp > cut1) {cut1 = posp;} if (pose > cut1) {cut1 = pose;} if (posq > cut1) {cut1 = posq;} if (posb > cut2) {cut2 = posb;} if (posX > cut2) {cut2 = posX;} if (posX-posb<20){cut2 = posb;}else{cut2 = posX;} //prefer cutting at ',' instead of the ' ' if the the ',' is less than 20 chars away.. for fluent speaking if (cut2>cut1){cutend = cut2;}else{cutend = cut1;} //prefer .:!? console.log ('----------------------------------------------------------'); console.log ('start: '+cutstart); console.log ('stop: '+cutend); var diff = oldlenght - cutend; console.log ('lenght: '+oldlenght); console.log ('diff: '+diff); if (readcounter === 1){ speakstring = currentLL.substr(cutstart, cutend); speakstring = speakstring.replaceAll(/(<([^>]+)>)/ig,' '); //replace all tags with ' ' }else{ var fixend = cutend - diff; console.log ('fixing end to: '+fixend); speakstring = currentLL.substr(cutstart, fixend); //WTF!!!! speakstring = speakstring.substr(0, (speakstring.length - diff)); speakstring = speakstring.replaceAll(/(<([^>]+)>)/ig,' '); } console.log ('readcounter:'+readcounter); console.log ('speakstring:'+speakstring); console.log ('----------------------------------------------------------'); const synth = window.speechSynthesis; //const voices = window.speechSynthesis.getVoices(); //console.log ('voices:'+voices.length); //const lastVoice = voices[2]; //console.log ('voice:'+lastVoice.name); //const lastVoice = voices[voices.length - 1]; const utterThis2 = new SpeechSynthesisUtterance(speakstring); //utterThis2.voice = lastVoice; utterThis2.voice = window.speechSynthesis.getVoices().find(voice => voice.voiceURI === voiceInEl.value); utterThis2.pitch = pitchInEl.value; utterThis2.rate = rateInEl.value; utterThis2.volume = volumeInEl.value; synth.speak(utterThis2); cutstart = cutend; //for next loop cycle if (currentLL.length === oldlenght){ // no change in text AI finisched writeing countnochange++; console.log ('count answer no change: '+countnochange); if (countnochange > 7){ //aftere 7 loops stop checking for changed answer clearInterval(myLoop); console.log ('count answer no change: '+countnochange); console.log ('stoped checking for answerchange'); countnochange = 0; } } }, delay); } } //end answer }); //Code from: https://codersblock.com/blog/javascript-text-to-speech-and-its-many-quirks/ // grab the UI elements to work with //const textEl = document.getElementById('text'); const voiceInEl = document.getElementById('voice'); const pitchInEl = document.getElementById('pitch'); const rateInEl = document.getElementById('rate'); const volumeInEl = document.getElementById('volume'); const pitchOutEl = document.querySelector('output[for="pitch"]'); const rateOutEl = document.querySelector('output[for="rate"]'); const volumeOutEl = document.querySelector('output[for="volume"]'); //const speakEl = document.getElementById('speak'); // add UI event handlers pitchInEl.addEventListener('change', updateOutputs); rateInEl.addEventListener('change', updateOutputs); volumeInEl.addEventListener('change', updateOutputs); //speakEl.addEventListener('click', speakText); // update voices immediately and whenever they are loaded updateVoices(); window.speechSynthesis.onvoiceschanged = updateVoices; function updateOutputs() { // display current values of all range inputs pitchOutEl.textContent = pitchInEl.value; rateOutEl.textContent = rateInEl.value; volumeOutEl.textContent = volumeInEl.value; } function updateVoices() { // add an option for each available voice that isn't already added window.speechSynthesis.getVoices().forEach(voice => { const isAlreadyAdded = [...voiceInEl.options].some(option => option.value === voice.voiceURI); if (!isAlreadyAdded) { const option = new Option(voice.name, voice.voiceURI, voice.default, voice.default); voiceInEl.add(option); } }); } /* let textelements = document.querySelectorAll('.flex.flex-col.w-full.py-2'); let element = textelements[0]; let textarea = element.querySelector('textarea'); textarea.value = textinput; */ /* document.addEventListener('DOMContentLoaded', function() { }); */