Last active
June 6, 2024 15:36
-
-
Save victornpb/e28bff8ebabf4da2f6d356e2f53a58a8 to your computer and use it in GitHub Desktop.
Chat GPT auto click continue generating
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// ==UserScript== | |
// @name Auto click Continue generating | |
// @namespace Violentmonkey Scripts | |
// @match https://chatgpt.com/* | |
// @match https://chat.openai.com/* | |
// @grant none | |
// @version 1.0 | |
// @description 6/4/2024, 6:45:45 PM | |
// ==/UserScript== | |
let stopTime = null; | |
let notifyTimeout = null; | |
let originalTitle = document.title; | |
let titleFlashInterval; | |
function generationStarted() { | |
console.log(`Generation started at: ${new Date(stopTime).toLocaleTimeString()}`); | |
if (notifyTimeout) { | |
clearTimeout(notifyTimeout); | |
notifyTimeout = null; | |
} | |
} | |
function generationStopped() { | |
const elapsedTime = (Date.now() - stopTime) / 1000; | |
console.log(`Generation stopped at: ${new Date().toLocaleTimeString()}, elapsed time: ${elapsedTime} seconds`); | |
// Check for continue generating button | |
const continueBtn = Array.from(document.querySelectorAll('button')).filter(btn => /Continue generating/i.test(btn.innerText)); | |
if (continueBtn.length) { | |
console.log('Auto clicking Continue generating...'); | |
continueBtn[0].click(); | |
} else { | |
console.log(`Generation stopped at: ${new Date().toLocaleTimeString()}, elapsed time: ${elapsedTime} seconds`); | |
// Send notification after it stopped generating | |
notifyTimeout = setTimeout(notify, 1000); | |
} | |
} | |
function notify() { | |
if (document.hidden) { | |
playBeep(); | |
triggerNotification(); | |
} else { | |
playBeep(0.2); // Quieter beep if visible | |
} | |
} | |
// Function to play a beep sound using the Web Audio API | |
function playBeep(volume = 1.0) { | |
const AudioContext = window.AudioContext || window.webkitAudioContext; | |
const audioCtx = new AudioContext(); | |
const oscillator = audioCtx.createOscillator(); | |
const gainNode = audioCtx.createGain(); | |
oscillator.connect(gainNode); | |
gainNode.connect(audioCtx.destination); | |
gainNode.gain.value = volume; | |
oscillator.type = 'square'; | |
oscillator.frequency.setValueAtTime(440, audioCtx.currentTime); // Frequency in hertz (A4) | |
oscillator.start(); | |
gainNode.gain.exponentialRampToValueAtTime(0.00001, audioCtx.currentTime + 1); // 1 second beep | |
oscillator.stop(audioCtx.currentTime + 1); | |
} | |
// Function to trigger a notification | |
function triggerNotification() { | |
if (Notification.permission === 'granted') { | |
console.log('Notification permission granted, triggering notification.'); | |
new Notification('Generation Stopped', { | |
body: 'The generation process has stopped.', | |
}); | |
} else { | |
console.log('Notification permission not granted.'); | |
} | |
} | |
// Function to check the button state | |
let previousState = ''; | |
function checkButtonState() { | |
const targetNode = document.querySelector('button[data-testid="fruitjuice-send-button"], button[data-testid="fruitjuice-stop-button"]'); | |
if (targetNode) { | |
const newValue = targetNode.getAttribute('data-testid'); | |
if (newValue !== previousState) { | |
if (newValue === 'fruitjuice-stop-button') { | |
if (!stopTime) { | |
stopTime = Date.now(); | |
generationStarted(); | |
} | |
} else if (newValue === 'fruitjuice-send-button' && stopTime) { | |
generationStopped(); | |
stopTime = null; // Reset stopTime | |
} | |
previousState = newValue; // Update previous state | |
} | |
} | |
} | |
// Throttling function with leading call | |
function throttle(func, delay) { | |
let lastCall = 0; | |
let timeoutId; | |
return function(...args) { | |
const now = new Date().getTime(); | |
if (now - lastCall < delay) { | |
clearTimeout(timeoutId); | |
timeoutId = setTimeout(() => { | |
lastCall = new Date().getTime(); | |
func(...args); | |
}, delay); | |
return; | |
} | |
lastCall = now; | |
func(...args); | |
}; | |
} | |
// Throttled version of checkButtonState | |
const throttledCheckButtonState = throttle(checkButtonState, 500); | |
const onReady = fn => document.readyState !== 'loading' ? fn() : document.addEventListener('DOMContentLoaded', fn); | |
onReady(() => { | |
// Set an observer on the body element to detect changes | |
const bodyObserver = new MutationObserver(throttledCheckButtonState); | |
bodyObserver.observe(document.body, { childList: true, subtree: true }); | |
// Initial check in case the button is already in the DOM | |
checkButtonState(); | |
// Request notification permission if not already granted | |
if (Notification.permission !== 'granted') { | |
Notification.requestPermission().then(permission => { | |
if (permission === 'granted') { | |
console.log('Notification permission granted.'); | |
} else { | |
console.log('Notification permission denied.'); | |
} | |
}).catch(error => { | |
console.error('Notification permission request error:', error); | |
}); | |
} else { | |
console.log('Notification permission already granted.'); | |
} | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How to use
Google chrome or similar
First install Violent Monkey extension
Then click the Raw button on this page to install this script.
Menu Bar X
Add custom JS

Just paste the code on the JS and click save