Skip to content

Instantly share code, notes, and snippets.

@victornpb
Last active June 6, 2024 15:36
Show Gist options
  • Save victornpb/e28bff8ebabf4da2f6d356e2f53a58a8 to your computer and use it in GitHub Desktop.
Save victornpb/e28bff8ebabf4da2f6d356e2f53a58a8 to your computer and use it in GitHub Desktop.
Chat GPT auto click continue generating
// ==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.');
}
});
@victornpb
Copy link
Author

victornpb commented Jun 4, 2024

How to use

Google chrome or similar

  1. First install Violent Monkey extension

  2. Then click the Raw button on this page to install this script.

Menu Bar X

Add custom JS
image

Just paste the code on the JS and click save

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment