Skip to content

Instantly share code, notes, and snippets.

@NightMachinery
Last active July 27, 2023 14:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save NightMachinery/4efb698fed669f00e7896e40b847dc4d to your computer and use it in GitHub Desktop.
Save NightMachinery/4efb698fed669f00e7896e40b847dc4d to your computer and use it in GitHub Desktop.
// ==UserScript==
// @name ChatGPT Hotkeys
// @description Refresh and Navigate ChatGPT
// @include https://chat.openai.com/*
// ==/UserScript==
(function () {
var url = 'https://chat.openai.com/?model=gpt-4';
var currentIndex = -1;
// Determine the platform and set the command key accordingly
var isMac = navigator.platform.toUpperCase().indexOf('MAC') >= 0;
var commandKey = isMac
? 'metaKey'
: 'ctrlKey';
function getCurrentIndex() {
var chatElements = document.querySelectorAll('li a');
for (var i = 0; i < chatElements.length; i++) {
if (chatElements[i].classList.contains('bg-gray-800')) {
return i;
}
}
return -1; // not found
}
function flashBlue(element, reset_p = true) {
// Save the current background color
let oldColor = element.style.backgroundColor;
// Change the background color to transparent blue
element.style.backgroundColor = 'rgba(0, 0, 255, 0.5)';
// After 500ms, change the color to transparent
setTimeout(() => {
element.style.backgroundColor = 'transparent';
// After another 500ms, change it back to the old color or clear it
setTimeout(() => {
if (reset_p) {
element.style.backgroundColor = '';
} else {
element.style.backgroundColor = oldColor;
}
}, 500);
}, 500);
}
function focusChat(index) {
var chatElements = document.querySelectorAll('li a'); // fetch updated chat elements
if (index >= 0 && index < chatElements.length) {
///
//: Remove focus style from previous element
// if (currentIndex !== index && chatElements[currentIndex]) {
// chatElements[currentIndex].style.backgroundColor = '';
// console.log('Removed focus style from element at index:', currentIndex);
// }
///
// Simulate click on current element
var clickEvent = new MouseEvent("click", {
bubbles: true,
cancelable: false
});
chatElements[index].dispatchEvent(clickEvent);
console.log('Simulated click on element at index:', index);
flashBlue(chatElements[index]);
currentIndex = index;
} else {
console.log('Cannot move focus, index out of bounds:', index);
}
}
function clickNewChatButton() {
// Get all <a> elements in the document
var aElements = document.querySelectorAll('a');
// Loop through all <a> elements
for (var i = 0; i < aElements.length; i++) {
// If the inner text of the <a> element is 'New chat'
if (aElements[i].innerText === 'New chat') {
// Simulate a click on the <a> element
aElements[i].click();
// Break the loop, no need to check other elements once we've found and clicked the 'New chat' button
break;
}
}
}
function clickModel(name, retry_after = 0.05, retry_count = 120) {
// Get all <button> elements in the document
var buttonElements = document.querySelectorAll('button');
// console.log('All buttons:', buttonElements); print all buttons
// Variable to track if button was found
var buttonFound = false;
// Loop through all <button> elements
for (var i = 0; i < buttonElements.length; i++) {
console.log('Button ' + (
i + 1) + ' inner text:', buttonElements[i].innerText); // print each button's inner text
// If the inner text of the <button> element contains 'name'
if (buttonElements[i].innerText.includes(name)) {
// Simulate a click on the <button> element
buttonElements[i].click();
console.log('Button clicked:', buttonElements[i]); // print the button that was clicked
// Mark button as found and break the loop, no need to check other elements once we've found and clicked the 'name' button
buttonFound = true;
break;
}
}
// If after looping through all buttons, none was found with the 'name', print a message
if (!buttonFound) {
console.log('Button with name not found');
if (retry_count > 0) {
console.log(`Retrying in ${retry_after} seconds... Remaining attempts: ${retry_count}`);
// Use setTimeout to wait for 'retry_after' seconds before trying again
setTimeout(function () {
clickModel(name, retry_after, retry_count - 1);
}, retry_after * 1000); // Convert retry_after from seconds to milliseconds
} else {
console.log("No more retries left.");
}
}
}
window.addEventListener('keydown', function (event) {
// Refresh the page
if (event[commandKey] && event.key === 'k') {
event.preventDefault();
console.log((
isMac
? 'CMD'
: 'CTRL') + ' + k pressed. Refreshing the page...');
// window.location.href = url;
clickNewChatButton();
setTimeout(function () {
clickModel('GPT-4');
}, 200);
}
// Navigate to next chat when Alt+Down is pressed
if (event.altKey && event.key === 'ArrowDown') {
event.preventDefault();
currentIndex = getCurrentIndex();
console.log('Alt + ArrowDown pressed. Moving to next chat...');
focusChat(currentIndex + 1);
}
// Navigate to previous chat when Alt+Up is pressed
if (event.altKey && event.key === 'ArrowUp') {
event.preventDefault();
currentIndex = getCurrentIndex();
console.log('Alt + ArrowUp pressed. Moving to previous chat...');
focusChat(currentIndex - 1);
}
});
console.log('Script loaded.');
}());
@NightMachinery
Copy link
Author

This userscript adds hotkey functionality to the OpenAI chat interface located at 'https://chat.openai.com/'. Here's a breakdown of its main features:

  1. It allows you to refresh the page by pressing 'CTRL + K' (or 'CMD + K' on Mac). This will reload the page and start a new chat with the GPT-4 model.

  2. It lets you navigate between different chat sessions. Specifically, you can:

    • Move to the next chat by pressing 'Alt + Down Arrow'
    • Move to the previous chat by pressing 'Alt + Up Arrow'

To use this userscript, you need to install a userscript manager extension on your browser such as Tampermonkey or Greasemonkey. After installing the manager, you can add this userscript.

Then, when you navigate to 'https://chat.openai.com/', you can use the hotkeys defined in the userscript to navigate through your chat sessions and refresh the page.

This script was developed with assistance from ChatGPT itself. :ouroboros:

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