Youtube Hide Recomended (English)

Automatically switches YouTube's recommendation column to either "From the series", "from (channel name)", or "Related"

当前为 2025-05-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Youtube Hide Recomended (English)
  3. // @name:ja YouTubeのリコメンド自動切換・非表示(英語環境用)
  4. // @version 2025-05-19
  5. // @description Automatically switches YouTube's recommendation column to either "From the series", "from (channel name)", or "Related"
  6. // @description:ja YouTubeのリコメンド欄を自動でFrom the series、from (チャンネル名)、Relatedのどれかに切り替えます
  7. // @author hirhirbyrd
  8. // @match https://www.youtube.com/*
  9. // @license MIT
  10. // @namespace https://greasyfork.org/users/1467931
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. let chname = '';
  17. let hasClicked = false; // ← 一度だけ実行するためのフラグ
  18.  
  19. const observerCallback = () => {
  20. if (!chname || hasClicked) return; // フラグで2回目以降はスキップ
  21.  
  22. const lists = document.querySelector('div#secondary-inner.style-scope.ytd-watch-flexy');
  23.  
  24. const elementC = document.querySelector('div#related iron-selector#chips yt-chip-cloud-chip-renderer:has(#text[title="From the series"])');
  25. const elementA = document.querySelector('div#related iron-selector#chips yt-chip-cloud-chip-renderer:has(#text[title="From ' + chname + '"])');
  26. const elementB = document.querySelector('div#related iron-selector#chips yt-chip-cloud-chip-renderer:has(#text[title="Related"])');
  27.  
  28. if (elementC && elementC.getAttribute('aria-selected') === 'false') {
  29. lists.hidden = false;
  30. elementC.click();
  31. hasClicked = true;
  32. } else if (elementA && elementA.getAttribute('aria-selected') === 'false') {
  33. lists.hidden = false;
  34. elementA.click();
  35. hasClicked = true;
  36. } else if (elementB && elementB.getAttribute('aria-selected') === 'false') {
  37. lists.hidden = false;
  38. elementB.click();
  39. hasClicked = true;
  40. } else if (elementC || elementA || elementAA || elementB) {
  41. // すでに選択済みの場合も処理完了とみなす
  42. hasClicked = true;
  43. } else {
  44. lists.hidden = true;
  45. }
  46. };
  47.  
  48. const getAuthorFromJSON = () => {
  49. const microformatScript = document.querySelector('#microformat script[type="application/ld+json"]');
  50. if (microformatScript) {
  51. try {
  52. const jsonData = JSON.parse(microformatScript.textContent);
  53. if (jsonData.author) {
  54. chname = typeof jsonData.author === 'string' ? jsonData.author : jsonData.author.name;
  55. console.log("チャンネル名を取得:", chname);
  56. observerCallback(); // 取得後すぐ実行
  57. }
  58. } catch (e) {
  59. console.error("author名の取得に失敗:", e);
  60. }
  61. }
  62. };
  63.  
  64. // DOMの変化を監視
  65. const observer = new MutationObserver(observerCallback);
  66. observer.observe(document, { childList: true, subtree: true });
  67.  
  68. // 初期読み込み時に author を取得
  69. window.addEventListener('load', () => {
  70. setTimeout(getAuthorFromJSON, 1000);
  71. });
  72.  
  73. })();