Auto-Select YouTube Subtitles by Sapioit

Automatically selects the YouTube subtitles with the text "English (auto-generated)"

  1. // ==UserScript==
  2. // @name Auto-Select YouTube Subtitles by Sapioit
  3. // @namespace Sapioit
  4. // @copyright Sapioit, 2020 - Present
  5. // @author sapioitgmail.com
  6. // @license GPL-2.0-only; http://www.gnu.org/licenses/gpl-2.0.txt
  7. // @version 2.15.0.3
  8. // @description Automatically selects the YouTube subtitles with the text "English (auto-generated)"
  9. // @match https://*.youtube.com/*
  10. // @match https://youtube.com/*
  11. // @match https://youtu.be/*
  12. // @icon https://youtube.com/favicon.ico
  13. // @grant none
  14. // ==/UserScript==
  15.  
  16.  
  17. var changed_page_= false;
  18. document.addEventListener('spfdone', function() {
  19. changed_page_ = true;
  20. //alert("changed link 1 spfdone");
  21. });
  22. document.addEventListener('transitionend', function(e) {
  23. //alert("changed link 2 transitionend");
  24. if (e.target.id === 'progress'){
  25. changed_page_ = true;
  26. //alert("changed link 2 transitionend progress");
  27. }
  28. });
  29. window.addEventListener('load', function () {
  30. changed_page_ = true;
  31. //alert("changed link 3 load");
  32. });
  33.  
  34. window.addEventListener('yt-page-data-updated', function () {
  35. changed_page_ = true;
  36. //alert("changed link 4 url change");
  37. });
  38.  
  39. function changed_link_(){
  40. if (changed_page_) {
  41. changed_page_ = false;
  42. return true;
  43. }
  44. return false;
  45. }
  46.  
  47.  
  48. localStorage.setItem('currentTitleValue', null);
  49. localStorage.setItem('consecutiveUnchangedCount', 0);
  50. let isFocused = () => typeof document.hidden !== undefined ? !document.hidden : null;
  51.  
  52. let repeatInterval = 5000; // 1000 milliseconds = 1 second; 10000 milliseconds = 10 second;
  53. let waitInterval = 5; // Adjust the delay (in milliseconds) if needed. 1000 = 1 second.
  54.  
  55. const userAgent = navigator.userAgent;
  56.  
  57. if (userAgent.includes("Chrome")) {
  58. // Code for Chrome
  59. console.log("Running on Chrome");
  60. // Change variables for Chrome
  61. } else if (userAgent.includes("Edg")) {
  62. // Code for Edge (Chromium-based Edge)
  63. console.log("Running on Edge");
  64. // Change variables for Edge
  65. let repeatInterval = 500; // 1000 milliseconds = 1 second; 10000 milliseconds = 10 second;
  66. let waitInterval = 1; // Adjust the delay (in milliseconds) if needed. 1000 = 1 second.
  67. } else {
  68. // Code for other browsers
  69. console.log("Running on a different browser");
  70. // Change variables for other browsers
  71. }
  72. setTimeout(() => {
  73. document.querySelectorAll('.ytp-settings-button').click();
  74. setTimeout(() => {
  75. document.querySelectorAll('.ytp-settings-button').click();
  76. }, waitInterval);
  77. }, waitInterval);
  78.  
  79.  
  80. function title_has_changed (count = 3) {
  81. console.info("%cAuto-Select YouTube Subtitles by Sapioit: changed_link(): %c" + changed_page_, "color: yellow; background-color: black;", "color: cyan");
  82. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed: %cChecking title.", "color: yellow; background-color: black;", "color: white");
  83. if (localStorage.getItem('currentTitleValue') === null) {
  84. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed: %cClicking the settigns button twice.", "color: yellow; background-color: black;", "color: white");
  85. }
  86.  
  87. // Check if the value of the title (the first "yt-formatted-string.style-scope.ytd-watch-metadata" element) has changed
  88. let currentTitleValue = document.querySelector('h1 yt-formatted-string.style-scope.ytd-watch-metadata');
  89. //let currentTitle = currentTitleValue ? currentTitleValue.innerHTML : '';
  90. currentTitleValue = currentTitleValue ? currentTitleValue.innerHTML : '';
  91.  
  92. if ( currentTitleValue === null || (typeof currentTitleValue) === 'undefined' || !currentTitleValue || currentTitleValue === '') {
  93. console.info("Auto-Select YouTube Subtitles by Sapioit: title_has_changed: %cThe 'h1 yt-formatted-string.style-scope.ytd-watch-metadata' is either NULL or UNDEFINED or empty.", "color: red");
  94. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed: %c", "color: red", "color: default", currentTitleValue , (typeof currentTitleValue));
  95. return false;
  96. }
  97.  
  98. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed:", "color: cyan", (currentTitleValue) );
  99. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed:", "color: cyan", (currentTitleValue !== '') , ' ' , (currentTitleValue) );
  100.  
  101. if ( currentTitleValue !== '' && currentTitleValue !== null) {
  102. // Get the current value of the title
  103. console.info("%cAuto-Select YouTube Subtitles by Sapioit: title_has_changed: %cTitle found.", "color: yellow; background-color: black;", "color: white");
  104.  
  105. // Get the consecutive unchanged count from localStorage, or set it to 0 if it's not available
  106. let consecutiveUnchangedCount = parseInt(localStorage.getItem('consecutiveUnchangedCount')) || 0;
  107.  
  108. // Increment the consecutiveUnchangedCount if the value is the same
  109. consecutiveUnchangedCount++;
  110.  
  111. // Update the stored value and consecutiveUnchangedCount in localStorage
  112. localStorage.setItem('currentTitleValue', currentTitleValue);
  113. localStorage.setItem('consecutiveUnchangedCount', consecutiveUnchangedCount.toString());
  114.  
  115. console.log("Auto-Select YouTube Subtitles by Sapioit: title_has_changed: Try nr #" + (1+consecutiveUnchangedCount) );
  116.  
  117. // Check if the current value is the same as the previous one stored in localStorage
  118. if (localStorage.getItem('currentTitleValue') === currentTitleValue) {
  119.  
  120. // Stop the function if the title value hasn't changed for the last three checks (consecutiveUnchangedCount is less than 4)
  121. if ( consecutiveUnchangedCount < (count+1) ) {
  122. console.log("Auto-Select YouTube Subtitles by Sapioit: title_has_changed: #" + (1+consecutiveUnchangedCount) + "First 'yt-formatted-string.style-scope.ytd-watch-metadata' element has not changed for the last three checks. Stopping check.");
  123. return false; // Return that the title has not changed.
  124. } else {
  125. // Reset the consecutiveUnchangedCount if the value has changed
  126. consecutiveUnchangedCount = 0;
  127.  
  128. // Update the stored value and consecutiveUnchangedCount in localStorage
  129. localStorage.setItem('currentTitleValue', currentTitleValue);
  130. localStorage.setItem('consecutiveUnchangedCount', consecutiveUnchangedCount.toString());
  131. return true; // Return that the title has changed.
  132. }
  133. } else {
  134. // Reset the consecutiveUnchangedCount if the value has changed
  135. consecutiveUnchangedCount = 0;
  136.  
  137. // Update the stored value and consecutiveUnchangedCount in localStorage
  138. localStorage.setItem('currentTitleValue', currentTitleValue);
  139. localStorage.setItem('consecutiveUnchangedCount', consecutiveUnchangedCount.toString());
  140. return true; // Return that the title has changed.
  141. }
  142. } else {
  143. console.log("Auto-Select YouTube Subtitles by Sapioit: title_has_changed: Checking title FAILED.");
  144. }
  145. return false; // Return that the title has changed.
  146. // Usage example:
  147. if ( title_has_changed() ){
  148. return;
  149. }
  150. if ( title_has_changed(3) ){
  151. return;
  152. }
  153. }
  154.  
  155.  
  156. function checkSubtitles() {
  157. if ( !isFocused() ){
  158. console.log("Youtube Hide Paused Gradient by Sapioit: swapButtonsSaveShare:: isFocused(): " + isFocused() );
  159. return;
  160. }
  161. if ( title_has_changed(12) ){
  162. console.log("Youtube Hide Paused Gradient by Sapioit: swapButtonsSaveShare:: title_has_changed(8): " + title_has_changed(8) );
  163. return;
  164. }
  165.  
  166. console.log("Auto-Select YouTube Subtitles by Sapioit: checkSubtitles: Checking subtitles.");
  167. // Check if the value of ytp-menuitem-content is 'English (auto-generated)'
  168. let menuItems = document.querySelectorAll('.ytp-menuitem');
  169. let subtitlesButton = document.querySelector('.ytp-subtitles-button');
  170. let autoGeneratedMenuItem;
  171.  
  172. for (let menuItem of menuItems) {
  173. let menuLabel = menuItem.querySelector('.ytp-menuitem-label span:first-child');
  174. let menuContent = menuItem.querySelector('.ytp-menuitem-content');
  175.  
  176. if ( menuLabel && menuLabel === 'Subtitles/CC'
  177. && menuContent && menuContent !== 'English (auto-generated)' ){
  178. autoGeneratedMenuItem = menuItem;
  179. break;
  180. }
  181. }
  182.  
  183. // Run the code if the condition is not met
  184. if (subtitlesButton && subtitlesButton.getAttribute('title') !== 'Subtitles/closed captions unavailable') {
  185. if (autoGeneratedMenuItem || subtitlesButton.getAttribute('aria-pressed') !== 'true' ) {
  186. // Change the subtitles
  187. //alert(subtitlesButton.outerHTML);
  188. ChangeSubtitles();
  189. } else {
  190. console.log("Auto-Select YouTube Subtitles by Sapioit: checkSubtitles: Subtitles did not need to be updated.");
  191. }
  192. } else {
  193. console.log("Auto-Select YouTube Subtitles by Sapioit: checkSubtitles: There are no subtitles available.");
  194. }
  195. }
  196.  
  197. // Schedule to run the code every so often
  198. setInterval(checkSubtitles, repeatInterval); // 1000 milliseconds = 1 second; 10000 milliseconds = 10 second;
  199.  
  200. window.addEventListener('DOMContentLoaded', () => {
  201. setTimeout(checkSubtitles, waitInterval);
  202. });
  203.  
  204. function ChangeSubtitles() {
  205. 'use strict';
  206.  
  207. // Find the gear icon
  208. //const gearIcon = document.querySelector('.ytp-settings-button');
  209. const gearIcon = document.querySelectorAll('.ytp-settings-button');
  210. console.log(gearIcon[0].outerHTML);
  211.  
  212. // Find the subtitles icon
  213. const subtitlesButton = document.querySelector('.ytp-subtitles-button');
  214.  
  215. // Click the gear icon to open the menu
  216. gearIcon[0].click();
  217. //document.querySelector('.ytp-settings-button').click();
  218.  
  219. // Wait for the menu to open
  220. setTimeout(() => {
  221. // Find the third menu item
  222. let menuItems = document.querySelectorAll('.ytp-menuitem-label span');
  223. let thirdMenuItem;
  224.  
  225. // Loop through each element in the 'menuItems' array.
  226. for (let j = 0; j < menuItems.length; j++) {
  227. // Get the current menu item element and its closest ancestor with the class 'ytp-menuitem'.
  228. let menuItem = menuItems[j].closest('.ytp-menuitem');
  229.  
  230. // If 'menuItem' exists and has a child with the class 'ytp-menuitem-label' that has the first child a 'span', and its text content is 'Subtitles/CC'.
  231. if (menuItem && menuItem.querySelector('.ytp-menuitem-label span:first-child').textContent.trim() === 'Subtitles/CC') {
  232. // If the condition is true, assign the 'menuItem' element to the variable 'thirdMenuItem'.
  233. thirdMenuItem = menuItem;
  234.  
  235. // Exit the loop immediately since the desired menu item is found.
  236. break;
  237. }
  238. }
  239.  
  240.  
  241. // Click the third menu item
  242. if (thirdMenuItem) {
  243. (thirdMenuItem).click();
  244. }
  245.  
  246. // Wait for the "Subtitles/CC" menu to open
  247. setTimeout(() => {
  248. // Find the "English (auto-generated)" menu item
  249. let menuLabels = document.querySelectorAll('.ytp-menuitem-label');
  250. let autoGeneratedMenuItem;
  251.  
  252. for (let i = 0; i < menuLabels.length; i++) {
  253. if (menuLabels[i].textContent.trim() === 'English (auto-generated)') {
  254. autoGeneratedMenuItem = menuLabels[i];
  255. break;
  256. }
  257. }
  258.  
  259. // Click the "English (auto-generated)" menu item if found
  260. if (autoGeneratedMenuItem) {
  261. (autoGeneratedMenuItem).click();
  262. }
  263. // Wait for the "English (auto-generated)" option to be selected
  264. setTimeout(() => {
  265. let element = document.querySelector('.ytp-settings-menu');
  266. let computedStyle = getComputedStyle(element);
  267. if (computedStyle.display !== 'none') {
  268. // Click the gear icon to open the menu
  269. gearIcon[0].click();
  270. }
  271. setTimeout(() => {
  272. if (subtitlesButton.getAttribute('aria-pressed') !== 'true') {
  273. //alert(subtitlesButton.outerHTML);
  274. (subtitlesButton).click();
  275. }
  276. }, waitInterval); // Adjust the delay (in milliseconds) if needed
  277. }, waitInterval); // Adjust the delay (in milliseconds) if needed
  278. }, waitInterval); // Adjust the delay (in milliseconds) if needed
  279. }, waitInterval); // Adjust the delay (in milliseconds) if needed
  280. console.log("Auto-Select YouTube Subtitles by Sapioit: ChangeSubtitles: Subtitles changed.");
  281. }