🏠 Home 

YouTube Auto Dislike

Because YouTube no longer displays the number of dislikes, the scripts automatically dislike all videos. Wait 15 seconds to see the effect.


Install this script?
  1. // ==UserScript==
  2. // @name YouTube Auto Dislike
  3. // @namespace gqqnbig
  4. // @match https://www.youtube.com/*
  5. // @grant none
  6. // @version 1.5
  7. // @author gqqnbig
  8. // @description Because YouTube no longer displays the number of dislikes, the scripts automatically dislike all videos. Wait 15 seconds to see the effect.
  9. // @license GNU General Public License v3.0
  10. // ==/UserScript==
  11. (function () {
  12. "use strict";
  13. //from https://github.com/Anarios/return-youtube-dislike/blob/main/Extensions/UserScript/Return%20Youtube%20Dislike.user.js
  14. const LIKED_STATE = "LIKED_STATE";
  15. const DISLIKED_STATE = "DISLIKED_STATE";
  16. const NEUTRAL_STATE = "NEUTRAL_STATE";
  17. let isShorts = () => location.pathname.startsWith("/shorts");
  18. function isInViewport(element) {
  19. const rect = element.getBoundingClientRect();
  20. const height = innerHeight || document.documentElement.clientHeight;
  21. const width = innerWidth || document.documentElement.clientWidth;
  22. return (
  23. // When short (channel) is ignored, the element (like/dislike AND short itself) is
  24. // hidden with a 0 DOMRect. In this case, consider it outside of Viewport
  25. !(rect.top == 0 && rect.left == 0 && rect.bottom == 0 && rect.right == 0) &&
  26. rect.top >= 0 &&
  27. rect.left >= 0 &&
  28. rect.bottom <= height &&
  29. rect.right <= width
  30. );
  31. }
  32. function getButtons() {
  33. if (isShorts()) {
  34. let elements = document.querySelectorAll("#like-button > ytd-like-button-renderer");
  35. for (let element of elements) {
  36. if (isInViewport(element)) {
  37. return element;
  38. }
  39. }
  40. }
  41. if (document.getElementById("menu-container")?.offsetParent === null) {
  42. return (
  43. document.querySelector("ytd-menu-renderer.ytd-watch-metadata > div") ??
  44. document.querySelector("ytd-menu-renderer.ytd-video-primary-info-renderer > div")
  45. );
  46. } else {
  47. return document
  48. .getElementById("menu-container")
  49. ?.querySelector("#top-level-buttons-computed");
  50. }
  51. }
  52. function getDislikeButton() {
  53. if (getButtons().children[0].tagName ===
  54. "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER") {
  55. if (getButtons().children[0].children[1] === undefined) {
  56. return document.querySelector("#segmented-dislike-button");
  57. } else {
  58. return getButtons().children[0].children[1];
  59. }
  60. } else {
  61. if (getButtons().querySelector("segmented-like-dislike-button-view-model")) {
  62. const dislikeViewModel = getButtons().querySelector("dislike-button-view-model");
  63. return dislikeViewModel;
  64. } else {
  65. return getButtons().children[1];
  66. }
  67. }
  68. }
  69. function getLikeButton() {
  70. return getButtons().children[0].tagName ===
  71. "YTD-SEGMENTED-LIKE-DISLIKE-BUTTON-RENDERER"
  72. ? document.querySelector("#segmented-like-button") !== null ? document.querySelector("#segmented-like-button") : getButtons().children[0].children[0]
  73. : getButtons().querySelector("like-button-view-model") ?? getButtons().children[0];
  74. }
  75. function isVideoLiked() {
  76. return getLikeButton().querySelector('button').getAttribute('aria-pressed') === 'true';
  77. }
  78. function isVideoDisliked() {
  79. return getDislikeButton().querySelector('button').getAttribute('aria-pressed') === 'true';
  80. }
  81. function getState() {
  82. if (isVideoLiked()) {
  83. return LIKED_STATE;
  84. }
  85. if (isVideoDisliked()) {
  86. return DISLIKED_STATE;
  87. }
  88. return NEUTRAL_STATE;
  89. }
  90. function isWatchPage() {
  91. return window.location.pathname.startsWith('/watch');
  92. }
  93. const observer = new MutationObserver((mutations) => {
  94. if (mutations.length > 0 && mutations[0].addedNodes.length > 0 && mutations[0].addedNodes[0].wholeText !== 'YouTube' &&
  95. isWatchPage()) {
  96. console.log('start unlike');
  97. // observer.disconnect(); // Stop observing temporarily
  98. setTimeout(() => {
  99. if (getState() === NEUTRAL_STATE) {
  100. getDislikeButton().querySelector('button').click();
  101. }
  102. }, 15000);
  103. // observer.observe(head, config);
  104. }
  105. });
  106. // only watch the direct children
  107. const config = {childList: true};
  108. let head;
  109. let getTitleHandle = setInterval(() => {
  110. head = document.head.querySelector('title');
  111. if (head) {
  112. observer.observe(head, config);
  113. clearInterval(getTitleHandle);
  114. }
  115. }, 200);
  116. })();