YouTube - Filter Subscriptions Page

hide videos with given title keywords

  1. // ==UserScript==
  2. // @name YouTube - Filter Subscriptions Page
  3. // @namespace https://zachhardesty.com
  4. // @author Zach Hardesty <zachhardesty7@users.noreply.github.com> (https://github.com/zachhardesty7)
  5. // @description hide videos with given title keywords
  6. // @copyright 2019-2024, Zach Hardesty (https://zachhardesty.com/)
  7. // @license GPL-3.0-only; http://www.gnu.org/licenses/gpl-3.0.txt
  8. // @version 2.1.0
  9.  
  10. // @grant GM_getValue
  11. // @grant GM_setValue
  12. // @grant GM_registerMenuCommand
  13.  
  14. // @homepageURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/youtube-filter-subscriptions-page.user.js
  15. // @homepage https://github.com/zachhardesty7/tamper-monkey-scripts-collection/raw/master/youtube-filter-subscriptions-page.user.js
  16. // @homepageURL https://openuserjs.org/scripts/zachhardesty7/YouTube_-_Filter_Subscriptions_Page
  17. // @homepage https://openuserjs.org/scripts/zachhardesty7/YouTube_-_Filter_Subscriptions_Page
  18. // @supportURL https://github.com/zachhardesty7/tamper-monkey-scripts-collection/issues
  19.  
  20.  
  21. // @match https://www.youtube.com/*
  22. // @require https://greasyfork.org/scripts/419640-onelementready/code/onElementReady.js?version=887637
  23. // ==/UserScript==
  24.  
  25. /* global onElementReady */
  26.  
  27. const HIDDEN_CLASSNAME = "zh-hidden"
  28.  
  29. let keywords = GM_getValue("yt-filter-page", "")
  30.  
  31. const stylesheet = document.createElement("style")
  32. const head = document.head || document.querySelectorAll("head")[0]
  33. stylesheet.id = "hiding" // to edit later
  34. stylesheet.type = "text/css"
  35. stylesheet.append(
  36. document.createTextNode(`
  37. .zh-hidden {
  38. display: none !important;
  39. }
  40. `),
  41. )
  42. head.append(stylesheet)
  43.  
  44. // runs on youtube.com/feed/subscriptions
  45. onElementReady(
  46. "#dismissible.style-scope.ytd-grid-video-renderer",
  47. { findOnce: false },
  48. (el) => {
  49. const videoTitle = el
  50. .querySelector("#details #meta")
  51. .firstElementChild.textContent.toLowerCase()
  52. const parentContainer = el.parentElement
  53.  
  54. for (const keyword of keywords.toLowerCase().split(",")) {
  55. if (keyword && videoTitle.includes(keyword)) {
  56. parentContainer.classList.add(HIDDEN_CLASSNAME)
  57. return
  58. }
  59. }
  60.  
  61. parentContainer.classList.remove(HIDDEN_CLASSNAME)
  62. },
  63. )
  64.  
  65. // runs on youtube.com
  66. onElementReady(
  67. "#dismissible.style-scope.ytd-rich-grid-media",
  68. { findOnce: false },
  69. (el) => {
  70. const videoTitle = el
  71. .querySelector("#details #meta")
  72. .firstElementChild.textContent.toLowerCase()
  73. const parentContainer = el.parentElement.parentElement.parentElement
  74.  
  75. for (const keyword of keywords.toLowerCase().split(",")) {
  76. if (keyword && videoTitle.includes(keyword)) {
  77. parentContainer.classList.add(HIDDEN_CLASSNAME)
  78. return
  79. }
  80. }
  81.  
  82. parentContainer.classList.remove(HIDDEN_CLASSNAME)
  83. },
  84. )
  85.  
  86. GM_registerMenuCommand("Set YT Filter Subscriptions Page Keywords", () => {
  87. // eslint-disable-next-line no-alert
  88. const val = prompt(
  89. "input a comma separated list of keywords (case insensitive)",
  90. keywords,
  91. )
  92.  
  93. if (val !== null) {
  94. keywords = val
  95. GM_setValue("yt-filter-page", val)
  96. }
  97. })