Auto Read Aloud ChatGPT

This JavaScript snippet is designed to automatically detect and interact with dynamically added “More actions” buttons on a web page and subsequently click the associated “Read aloud” button. It simulates real user interactions by triggering all relevant mouse events, ensuring the UI responds as if a human clicked.

目前為 2025-09-14 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Auto Read Aloud ChatGPT
// @namespace    http://tampermonkey.net/
// @version      2025-09-14
// @description  This JavaScript snippet is designed to automatically detect and interact with dynamically added “More actions” buttons on a web page and subsequently click the associated “Read aloud” button. It simulates real user interactions by triggering all relevant mouse events, ensuring the UI responds as if a human clicked.
// @author       You
// @match        https://chatgpt.com/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=chatgpt.com
// @grant        none
// @license MIT
// ==/UserScript==

(function() {
    'use strict';

    // Function to simulate a full user click
function simulateFullClick(el) {
  const events = [
    'pointerover',
    'pointerenter',
    'mouseover',
    'mouseenter',
    'mousemove',
    'pointerdown',
    'mousedown',
    'pointerup',
    'mouseup',
    'click'
  ];

  events.forEach(type => {
    const event = new MouseEvent(type, {
      bubbles: true,
      cancelable: true,
      view: window,
      clientX: 0,
      clientY: 0,
      button: 0
    });
    el.dispatchEvent(event);
  });
}

// Function to handle a new "More actions" button
function onNewButton(newButton) {
  console.log('New "More actions" button detected:', newButton);

  // Click the "More actions" button
  simulateFullClick(newButton);

  // Wait for the menu to appear, then click "Read aloud"
  setTimeout(() => {
    const readAloudButton = document.querySelector('[aria-label="Read aloud"]');
    if (readAloudButton) {
      simulateFullClick(readAloudButton);
      console.log('"Read aloud" button clicked!');
    } else {
      console.log('"Read aloud" button not found yet.');
    }
  }, 200); // Adjust delay if menu is slow
}

// Observe the document for new nodes
const observer = new MutationObserver(mutations => {
  mutations.forEach(mutation => {
    mutation.addedNodes.forEach(node => {
      if (node.nodeType === 1) { // element node
        // Check if the added node is a "More actions" button
        if (node.matches('button[aria-label="More actions"]')) {
          onNewButton(node);
        }

        // Also check if any descendants are "More actions" buttons
        node.querySelectorAll?.('button[aria-label="More actions"]').forEach(btn => {
          onNewButton(btn);
        });
      }
    });
  });
});

// Start observing
observer.observe(document.body, { childList: true, subtree: true });
console.log('Watching for new "More actions" buttons...');

})();