Skip to content

Instantly share code, notes, and snippets.

@victornpb
Last active June 6, 2024 15:36
Show Gist options
  • Select an option

  • Save victornpb/e28bff8ebabf4da2f6d356e2f53a58a8 to your computer and use it in GitHub Desktop.

Select an option

Save victornpb/e28bff8ebabf4da2f6d356e2f53a58a8 to your computer and use it in GitHub Desktop.

Revisions

  1. victornpb revised this gist Jun 4, 2024. 1 changed file with 28 additions and 21 deletions.
    49 changes: 28 additions & 21 deletions chatgpt-autocontinue.user.js
    Original file line number Diff line number Diff line change
    @@ -118,24 +118,31 @@ function throttle(func, delay) {
    // Throttled version of checkButtonState
    const throttledCheckButtonState = throttle(checkButtonState, 500);

    // 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.');
    }
    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.');
    }

    });

  2. victornpb revised this gist Jun 4, 2024. 1 changed file with 129 additions and 12 deletions.
    141 changes: 129 additions & 12 deletions chatgpt-autocontinue.user.js
    Original file line number Diff line number Diff line change
    @@ -5,20 +5,137 @@
    // @match https://chat.openai.com/*
    // @grant none
    // @version 1.0
    // @author -
    // @description 6/4/2024, 6:45:45 PM
    // ==/UserScript==

    let stopTime = null;
    let notifyTimeout = null;
    let originalTitle = document.title;
    let titleFlashInterval;

    let lastClicked = 0;
    function generationStarted() {
    console.log(`Generation started at: ${new Date(stopTime).toLocaleTimeString()}`);
    if (notifyTimeout) {
    clearTimeout(notifyTimeout);
    notifyTimeout = null;
    }
    }

    setInterval(() => {
    if (Date.now() - lastClicked < 5000) return; // don't spam the 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();
    lastClicked = Date.now();
    }
    }, 1000);
    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);

    // 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.');
    }
  3. victornpb created this gist Jun 4, 2024.
    24 changes: 24 additions & 0 deletions chatgpt-autocontinue.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,24 @@
    // ==UserScript==
    // @name Auto click Continue generating
    // @namespace Violentmonkey Scripts
    // @match https://chatgpt.com/*
    // @match https://chat.openai.com/*
    // @grant none
    // @version 1.0
    // @author -
    // @description 6/4/2024, 6:45:45 PM
    // ==/UserScript==


    let lastClicked = 0;

    setInterval(() => {
    if (Date.now() - lastClicked < 5000) return; // don't spam the 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();
    lastClicked = Date.now();
    }
    }, 1000);